Commit FS#12321 - Touchscreen: List line padding, to more easily select lines
This adds line padding to lists on touchscreens, in order to make lists reasonably useful without huge fonts. It's configurable: * Automatic (default, line height calculated using a lcd dpi aware function) * Off (status quo, line height = font height) * X pixels (from 2 to 50 in even steps) The automatic setting should/aims to Just Work Out Of The Box on all targets git-svn-id: svn://svn.rockbox.org/rockbox/trunk@30773 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
parent
859cd4b627
commit
3b12634e6b
12 changed files with 154 additions and 42 deletions
|
@ -102,13 +102,15 @@ static bool draw_title(struct screen *display, struct gui_synclist *list)
|
|||
if (!list_display_title(list, screen))
|
||||
return false;
|
||||
*title_text_vp = *(list->parent[screen]);
|
||||
title_text_vp->height = font_get(title_text_vp->font)->height;
|
||||
title_text_vp->height = title_text_vp->line_height;
|
||||
|
||||
if (list->title_icon != Icon_NOICON && global_settings.show_icons)
|
||||
{
|
||||
struct viewport title_icon = *title_text_vp;
|
||||
|
||||
title_icon.width = get_icon_width(screen) + ICON_PADDING * 2;
|
||||
title_icon.y += (title_icon.height - get_icon_height(screen)) / 2;
|
||||
title_icon.height = get_icon_height(screen);
|
||||
if (VP_IS_RTL(&title_icon))
|
||||
{
|
||||
title_icon.x += title_text_vp->width - title_icon.width;
|
||||
|
@ -120,7 +122,7 @@ static bool draw_title(struct screen *display, struct gui_synclist *list)
|
|||
title_text_vp->width -= title_icon.width;
|
||||
|
||||
display->set_viewport(&title_icon);
|
||||
screen_put_icon(display, 0, 0, list->title_icon);
|
||||
screen_put_iconxy(display, 0, 0, list->title_icon);
|
||||
}
|
||||
#ifdef HAVE_LCD_COLOR
|
||||
if (list->title_color >= 0)
|
||||
|
@ -136,7 +138,7 @@ static bool draw_title(struct screen *display, struct gui_synclist *list)
|
|||
void list_draw(struct screen *display, struct gui_synclist *list)
|
||||
{
|
||||
struct viewport list_icons;
|
||||
int start, end, line_height, style, i;
|
||||
int start, end, line_height, style, item_offset, i;
|
||||
const int screen = display->screen_type;
|
||||
const int list_start_item = list->start_item[screen];
|
||||
const int icon_width = get_icon_width(screen) + ICON_PADDING;
|
||||
|
@ -147,19 +149,21 @@ void list_draw(struct screen *display, struct gui_synclist *list)
|
|||
#ifdef HAVE_LCD_COLOR
|
||||
unsigned char cur_line = 0;
|
||||
#endif
|
||||
int item_offset;
|
||||
int icon_yoffset = 0; /* to center the icon */
|
||||
bool show_title;
|
||||
struct viewport *list_text_vp = &list_text[screen];
|
||||
|
||||
line_height = font_get(parent->font)->height;
|
||||
line_height = parent->line_height;
|
||||
display->set_viewport(parent);
|
||||
display->clear_viewport();
|
||||
display->scroll_stop(list_text_vp);
|
||||
*list_text_vp = *parent;
|
||||
list_text_vp->line_height = line_height;
|
||||
if ((show_title = draw_title(display, list)))
|
||||
{
|
||||
list_text_vp->y += line_height;
|
||||
list_text_vp->height -= line_height;
|
||||
int title_height = title_text[screen].height;
|
||||
list_text_vp->y += title_height;
|
||||
list_text_vp->height -= title_height;
|
||||
}
|
||||
|
||||
const int nb_lines = viewport_get_nb_lines(list_text_vp);
|
||||
|
@ -232,6 +236,7 @@ void list_draw(struct screen *display, struct gui_synclist *list)
|
|||
list_icons.x += list_text_vp->width + ICON_PADDING;
|
||||
else
|
||||
list_text_vp->x += list_icons.width + ICON_PADDING;
|
||||
icon_yoffset = (line_height - get_icon_height(screen)) / 2;
|
||||
}
|
||||
|
||||
for (i=start; i<end && i<list->nb_items; i++)
|
||||
|
@ -333,14 +338,18 @@ void list_draw(struct screen *display, struct gui_synclist *list)
|
|||
display->set_viewport(&list_icons);
|
||||
if (list->callback_get_item_icon != NULL)
|
||||
{
|
||||
screen_put_icon_with_offset(display, show_cursor?1:0,
|
||||
(line),show_cursor?ICON_PADDING:0,draw_offset,
|
||||
list->callback_get_item_icon(i, list->data));
|
||||
int xoff = show_cursor ? get_icon_width(screen) + ICON_PADDING : 0;
|
||||
screen_put_iconxy(display, xoff,
|
||||
line*line_height + draw_offset + icon_yoffset,
|
||||
list->callback_get_item_icon(i, list->data));
|
||||
}
|
||||
/* do the cursor */
|
||||
if (show_cursor && i >= list->selected_item &&
|
||||
i < list->selected_item + list->selected_size)
|
||||
{
|
||||
screen_put_icon_with_offset(display, 0, line, 0, draw_offset, Icon_Cursor);
|
||||
screen_put_iconxy(display, 0,
|
||||
line*line_height + draw_offset + icon_yoffset,
|
||||
Icon_Cursor);
|
||||
}
|
||||
}
|
||||
display->set_viewport(parent);
|
||||
|
@ -369,8 +378,7 @@ static int scrollbar_scroll(struct gui_synclist * gui_list,
|
|||
{
|
||||
/* scrollbar scrolling is still line based */
|
||||
y_offset = 0;
|
||||
int scrollbar_size = nb_lines*
|
||||
font_get(gui_list->parent[screen]->font)->height;
|
||||
int scrollbar_size = nb_lines*gui_list->parent[screen]->line_height;
|
||||
int actual_y = y - list_text[screen].y;
|
||||
|
||||
int new_selection = (actual_y * gui_list->nb_items)
|
||||
|
@ -558,7 +566,7 @@ static int kinetic_callback(struct timeout *tmo)
|
|||
return 0;
|
||||
|
||||
struct cb_data *data = (struct cb_data*)tmo->data;
|
||||
int line_height = font_get(data->list->parent[0]->font)->height;
|
||||
int line_height = data->list->parent[0]->line_height;
|
||||
/* ds = v*dt */
|
||||
int pixel_diff = data->velocity * RELOAD_INTERVAL / HZ;
|
||||
/* remember signedness to detect stopping */
|
||||
|
@ -627,7 +635,7 @@ unsigned gui_synclist_do_touchscreen(struct gui_synclist * gui_list)
|
|||
struct viewport *parent = gui_list->parent[screen];
|
||||
const int button = action_get_touchscreen_press_in_vp(&x, &y, parent);
|
||||
const int list_start_item = gui_list->start_item[screen];
|
||||
const int line_height = font_get(gui_list->parent[screen]->font)->height;
|
||||
const int line_height = gui_list->parent[screen]->line_height;
|
||||
const struct viewport *list_text_vp = &list_text[screen];
|
||||
const bool old_released = released;
|
||||
const bool show_title = list_display_title(gui_list, screen);
|
||||
|
|
|
@ -277,3 +277,8 @@ int get_icon_width(enum screen_type screen_type)
|
|||
{
|
||||
return ICON_WIDTH(screen_type);
|
||||
}
|
||||
|
||||
int get_icon_height(enum screen_type screen_type)
|
||||
{
|
||||
return ICON_HEIGHT(screen_type);
|
||||
}
|
||||
|
|
|
@ -109,8 +109,11 @@ void icons_init(void);
|
|||
#ifdef HAVE_LCD_CHARCELLS
|
||||
# define CURSOR_CHAR 0xe10c
|
||||
# define get_icon_width(a) 6
|
||||
# define get_icon_height(a) 1 /* needs to be verified */
|
||||
#else
|
||||
int get_icon_width(enum screen_type screen_type);
|
||||
int get_icon_height(enum screen_type screen_type);
|
||||
#endif
|
||||
|
||||
|
||||
#endif /*_GUI_ICON_H_*/
|
||||
|
|
|
@ -78,6 +78,21 @@ void list_init(void)
|
|||
add_event(GUI_EVENT_THEME_CHANGED, false, list_force_reinit);
|
||||
}
|
||||
|
||||
#ifdef HAVE_TOUCHSCREEN
|
||||
static int line_height_from_lcd_dpi(const struct viewport *vp)
|
||||
{
|
||||
/* the 4/12 factor is designed for reasonable item size on a 160dpi screen */
|
||||
return MAX(lcd_get_dpi()*4/12, (int)font_get(vp->font)->height);
|
||||
}
|
||||
|
||||
static int list_line_height(const struct viewport *vp)
|
||||
{
|
||||
if (global_settings.list_line_padding == -1)
|
||||
return line_height_from_lcd_dpi(vp);
|
||||
return font_get(vp->font)->height + global_settings.list_line_padding;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void list_init_viewports(struct gui_synclist *list)
|
||||
{
|
||||
int parent_used;
|
||||
|
@ -90,6 +105,9 @@ static void list_init_viewports(struct gui_synclist *list)
|
|||
{
|
||||
list->parent[i] = &parent[i];
|
||||
viewport_set_defaults(&parent[i], i);
|
||||
#ifdef HAVE_TOUCHSCREEN
|
||||
parent[i].line_height = list_line_height(list->parent[i]);
|
||||
#endif
|
||||
#ifdef HAVE_BUTTONBAR
|
||||
if (screens[i].has_buttonbar)
|
||||
list->parent[i]->height -= BUTTONBAR_HEIGHT;
|
||||
|
@ -124,13 +142,15 @@ bool list_display_title(struct gui_synclist *list, enum screen_type screen)
|
|||
|
||||
static int list_get_nb_lines(struct gui_synclist *list, enum screen_type screen)
|
||||
{
|
||||
struct viewport vp = *list->parent[screen];
|
||||
int skin_count = skinlist_get_line_count(screen, list);
|
||||
if (skin_count >= 0)
|
||||
return skin_count;
|
||||
if (list_display_title(list, screen))
|
||||
vp.height -= font_get(list->parent[screen]->font)->height;
|
||||
return viewport_get_nb_lines(&vp);
|
||||
struct viewport *vp = list->parent[screen];
|
||||
int lines = skinlist_get_line_count(screen, list);
|
||||
if (lines < 0)
|
||||
{
|
||||
lines = viewport_get_nb_lines(vp);
|
||||
if (list_display_title(list, screen))
|
||||
lines -= 1;
|
||||
}
|
||||
return lines;
|
||||
}
|
||||
#else
|
||||
#define list_display_title(l, i) false
|
||||
|
|
|
@ -223,7 +223,7 @@ static bool is_theme_enabled(enum screen_type screen)
|
|||
int viewport_get_nb_lines(const struct viewport *vp)
|
||||
{
|
||||
#ifdef HAVE_LCD_BITMAP
|
||||
return vp->height/font_get(vp->font)->height;
|
||||
return vp->height/vp->line_height;
|
||||
#else
|
||||
(void)vp;
|
||||
return 2;
|
||||
|
@ -318,6 +318,7 @@ void viewport_set_fullscreen(struct viewport *vp,
|
|||
set_default_align_flags(vp);
|
||||
#endif
|
||||
vp->font = global_status.font_id[screen];
|
||||
vp->line_height = font_get(vp->font)->height;
|
||||
vp->drawmode = DRMODE_SOLID;
|
||||
#if LCD_DEPTH > 1
|
||||
#ifdef HAVE_REMOTE_LCD
|
||||
|
|
|
@ -35,6 +35,7 @@ int viewport_get_nb_lines(const struct viewport *vp);
|
|||
#define THEME_UI_VIEWPORT (BIT_N(1))
|
||||
#define THEME_BUTTONBAR (BIT_N(2))
|
||||
#define THEME_LANGUAGE (BIT_N(3))
|
||||
#define THEME_LISTS (BIT_N(3))
|
||||
#define THEME_ALL (~(0u))
|
||||
|
||||
#ifndef __PCTOOL__
|
||||
|
|
|
@ -12830,3 +12830,34 @@
|
|||
multidrive_usb: "USB Hide Internal Drive"
|
||||
</voice>
|
||||
</phrase>
|
||||
<phrase>
|
||||
id: LANG_LIST_LINE_PADDING
|
||||
desc: list padding, in display settings
|
||||
user: core
|
||||
<source>
|
||||
*: none
|
||||
touchscreen: "Line Padding in Lists"
|
||||
</source>
|
||||
<dest>
|
||||
*: none
|
||||
touchscreen: "Line Padding in Lists"
|
||||
</dest>
|
||||
<voice>
|
||||
*: none
|
||||
touchscreen: "Line Padding in Lists"
|
||||
</voice>
|
||||
</phrase>
|
||||
<phrase>
|
||||
id: LANG_AUTOMATIC
|
||||
desc: generic automatic
|
||||
user: core
|
||||
<source>
|
||||
*: "Automatic"
|
||||
</source>
|
||||
<dest>
|
||||
*: "Automatic"
|
||||
</dest>
|
||||
<voice>
|
||||
*: "Automatic"
|
||||
</voice>
|
||||
</phrase>
|
||||
|
|
|
@ -500,14 +500,25 @@ static int touch_mode_callback(int action,const struct menu_item_ex *this_item)
|
|||
}
|
||||
return action;
|
||||
}
|
||||
|
||||
static int line_padding_callback(int action,const struct menu_item_ex *this_item)
|
||||
{
|
||||
(void)this_item;
|
||||
|
||||
if (action == ACTION_EXIT_MENUITEM)
|
||||
viewportmanager_theme_changed(THEME_LISTS);
|
||||
return action;
|
||||
}
|
||||
|
||||
MENUITEM_SETTING(touch_mode, &global_settings.touch_mode, touch_mode_callback);
|
||||
|
||||
MENUITEM_FUNCTION(touchscreen_menu_calibrate, 0, ID2P(LANG_TOUCHSCREEN_CALIBRATE), calibrate,
|
||||
NULL, NULL, Icon_NOICON);
|
||||
MENUITEM_FUNCTION(touchscreen_menu_reset_calibration, 0, ID2P(LANG_TOUCHSCREEN_RESET_CALIBRATION), reset_mapping,
|
||||
NULL, NULL, Icon_NOICON);
|
||||
MENUITEM_SETTING(list_line_padding, &global_settings.list_line_padding, line_padding_callback);
|
||||
|
||||
MAKE_MENU(touchscreen_menu, ID2P(LANG_TOUCHSCREEN_SETTINGS), NULL, Icon_NOICON, &touch_mode,
|
||||
MAKE_MENU(touchscreen_menu, ID2P(LANG_TOUCHSCREEN_SETTINGS), NULL, Icon_NOICON, &list_line_padding, &touch_mode,
|
||||
&touchscreen_menu_calibrate, &touchscreen_menu_reset_calibration);
|
||||
#endif
|
||||
|
||||
|
|
|
@ -562,6 +562,10 @@ struct user_settings
|
|||
int scrollbar_width;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_TOUCHSCREEN
|
||||
int list_line_padding;
|
||||
#endif
|
||||
|
||||
/* goto current song when exiting WPS */
|
||||
bool browse_current; /* 1=goto current song,
|
||||
0=goto previous location */
|
||||
|
|
|
@ -286,6 +286,29 @@ static const char graphic_numeric[] = "graphic,numeric";
|
|||
|
||||
#endif /* HAVE_RECORDING */
|
||||
|
||||
static const char* list_pad_formatter(char *buffer, size_t buffer_size,
|
||||
int val, const char *unit)
|
||||
{
|
||||
switch (val)
|
||||
{
|
||||
case -1: return str(LANG_AUTOMATIC);
|
||||
case 0: return str(LANG_OFF);
|
||||
default: break;
|
||||
}
|
||||
snprintf(buffer, buffer_size, "%d %s", val, unit);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static int32_t list_pad_getlang(int value, int unit)
|
||||
{
|
||||
switch (value)
|
||||
{
|
||||
case -1: return LANG_AUTOMATIC;
|
||||
case 0: return LANG_OFF;
|
||||
default: return TALK_ID(value, unit);
|
||||
}
|
||||
}
|
||||
|
||||
static const char* formatter_unit_0_is_off(char *buffer, size_t buffer_size,
|
||||
int val, const char *unit)
|
||||
{
|
||||
|
@ -740,6 +763,12 @@ const struct settings_list settings[] = {
|
|||
INT_SETTING(F_THEMESETTING, scrollbar_width, LANG_SCROLLBAR_WIDTH, 6,
|
||||
"scrollbar width",UNIT_INT, 3, MAX(LCD_WIDTH/10,25), 1,
|
||||
NULL, NULL, NULL),
|
||||
#ifdef HAVE_TOUCHSCREEN
|
||||
TABLE_SETTING(F_ALLOW_ARBITRARY_VALS, list_line_padding, LANG_LIST_LINE_PADDING,
|
||||
-1, "list padding", "off,auto", UNIT_PIXEL, list_pad_formatter,
|
||||
list_pad_getlang, NULL, 16,
|
||||
-1,0,2,4,6,8,10,12,16,20,24,28,32,38,44,50),
|
||||
#endif
|
||||
#if CONFIG_KEYPAD == RECORDER_PAD
|
||||
OFFON_SETTING(F_THEMESETTING,buttonbar, LANG_BUTTON_BAR ,true,"buttonbar", NULL),
|
||||
#endif
|
||||
|
|
|
@ -254,11 +254,12 @@ void LCDFN(putsxyf)(int x, int y, const unsigned char *fmt, ...)
|
|||
|
||||
static void LCDFN(putsxyofs_style)(int xpos, int ypos,
|
||||
const unsigned char *str, int style,
|
||||
int w, int h, int offset)
|
||||
int h, int offset)
|
||||
{
|
||||
int lastmode = current_vp->drawmode;
|
||||
int xrect = xpos + MAX(w - offset, 0);
|
||||
int x = VP_IS_RTL(current_vp) ? xpos : xrect;
|
||||
int text_ypos = ypos;
|
||||
int line_height = font_get(current_vp->font)->height;
|
||||
text_ypos += h/2 - line_height/2; /* center the text in the line */
|
||||
#if defined(MAIN_LCD) && defined(HAVE_LCD_COLOR)
|
||||
int oldfgcolor = current_vp->fg_pattern;
|
||||
int oldbgcolor = current_vp->bg_pattern;
|
||||
|
@ -284,21 +285,21 @@ static void LCDFN(putsxyofs_style)(int xpos, int ypos,
|
|||
current_vp->fg_pattern = current_vp->lst_pattern;
|
||||
}
|
||||
else {
|
||||
lcd_fillrect(x, ypos, current_vp->width - xrect, h);
|
||||
lcd_fillrect(xpos, ypos, current_vp->width - xpos, h);
|
||||
current_vp->drawmode = (style & STYLE_INVERT) ?
|
||||
(DRMODE_SOLID|DRMODE_INVERSEVID) : DRMODE_SOLID;
|
||||
}
|
||||
if (str[0])
|
||||
lcd_putsxyofs(xpos, ypos, offset, str);
|
||||
lcd_putsxyofs(xpos, text_ypos, offset, str);
|
||||
current_vp->fg_pattern = oldfgcolor;
|
||||
current_vp->bg_pattern = oldbgcolor;
|
||||
#else
|
||||
current_vp->drawmode = DRMODE_SOLID | ((style & STYLE_INVERT) ?
|
||||
0 : DRMODE_INVERSEVID);
|
||||
LCDFN(fillrect)(x, ypos, current_vp->width - xrect, h);
|
||||
LCDFN(fillrect)(xpos, ypos, current_vp->width - xpos, h);
|
||||
current_vp->drawmode ^= DRMODE_INVERSEVID;
|
||||
if (str[0])
|
||||
LCDFN(putsxyofs)(xpos, ypos, offset, str);
|
||||
LCDFN(putsxyofs)(xpos, text_ypos, offset, str);
|
||||
#endif
|
||||
current_vp->drawmode = lastmode;
|
||||
}
|
||||
|
@ -309,15 +310,15 @@ static void LCDFN(putsxyofs_style)(int xpos, int ypos,
|
|||
void LCDFN(puts_style_xyoffset)(int x, int y, const unsigned char *str,
|
||||
int style, int x_offset, int y_offset)
|
||||
{
|
||||
int xpos, ypos, w, h;
|
||||
int xpos, ypos, h;
|
||||
LCDFN(scroll_stop_line)(current_vp, y);
|
||||
if(!str)
|
||||
return;
|
||||
|
||||
LCDFN(getstringsize)(str, &w, &h);
|
||||
h = current_vp->line_height ?: (int)font_get(current_vp->font)->height;
|
||||
xpos = x * LCDFN(getstringsize)(" ", NULL, NULL);
|
||||
ypos = y * h + y_offset;
|
||||
LCDFN(putsxyofs_style)(xpos, ypos, str, style, w, h, x_offset);
|
||||
LCDFN(putsxyofs_style)(xpos, ypos, str, style, h, x_offset);
|
||||
}
|
||||
|
||||
void LCDFN(puts_style_offset)(int x, int y, const unsigned char *str,
|
||||
|
@ -436,10 +437,9 @@ void LCDFN(puts_scroll_offset)(int x, int y, const unsigned char *string,
|
|||
|
||||
void LCDFN(scroll_fn)(void)
|
||||
{
|
||||
struct font* pf;
|
||||
struct scrollinfo* s;
|
||||
int index;
|
||||
int xpos, ypos;
|
||||
int xpos, ypos, height;
|
||||
struct viewport* old_vp = current_vp;
|
||||
bool makedelay;
|
||||
|
||||
|
@ -451,15 +451,15 @@ void LCDFN(scroll_fn)(void)
|
|||
continue;
|
||||
|
||||
LCDFN(set_viewport)(s->vp);
|
||||
height = s->vp->line_height;
|
||||
|
||||
if (s->backward)
|
||||
s->offset -= LCDFN(scroll_info).step;
|
||||
else
|
||||
s->offset += LCDFN(scroll_info).step;
|
||||
|
||||
pf = font_get(current_vp->font);
|
||||
xpos = s->startx;
|
||||
ypos = s->y * pf->height + s->y_offset;
|
||||
ypos = s->y * height + s->y_offset;
|
||||
|
||||
makedelay = false;
|
||||
if (s->bidir) { /* scroll bidirectional */
|
||||
|
@ -488,10 +488,8 @@ void LCDFN(scroll_fn)(void)
|
|||
s->start_tick = current_tick + LCDFN(scroll_info).delay +
|
||||
LCDFN(scroll_info).ticks;
|
||||
|
||||
LCDFN(putsxyofs_style)(xpos, ypos, s->line, s->style, s->width,
|
||||
pf->height, s->offset);
|
||||
LCDFN(update_viewport_rect)(xpos, ypos, current_vp->width - xpos,
|
||||
pf->height);
|
||||
LCDFN(putsxyofs_style)(xpos, ypos, s->line, s->style, height, s->offset);
|
||||
LCDFN(update_viewport_rect)(xpos, ypos, current_vp->width-xpos, height);
|
||||
}
|
||||
LCDFN(set_viewport)(old_vp);
|
||||
}
|
||||
|
|
|
@ -43,6 +43,7 @@ struct viewport {
|
|||
#ifdef HAVE_LCD_BITMAP
|
||||
int flags;
|
||||
int font;
|
||||
int line_height;
|
||||
int drawmode;
|
||||
#endif
|
||||
#if LCD_DEPTH > 1
|
||||
|
|
Loading…
Reference in a new issue