From 3b12634e6bc966cb2b2e7f21e9a435cdd20f0bc4 Mon Sep 17 00:00:00 2001 From: Thomas Martitz Date: Mon, 17 Oct 2011 17:38:10 +0000 Subject: 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 --- apps/gui/bitmap/list.c | 38 ++++++++++++++++++++++-------------- apps/gui/icon.c | 5 +++++ apps/gui/icon.h | 3 +++ apps/gui/list.c | 34 +++++++++++++++++++++++++------- apps/gui/viewport.c | 3 ++- apps/gui/viewport.h | 1 + apps/lang/english.lang | 31 +++++++++++++++++++++++++++++ apps/menus/display_menu.c | 13 +++++++++++- apps/settings.h | 4 ++++ apps/settings_list.c | 29 +++++++++++++++++++++++++++ firmware/drivers/lcd-bitmap-common.c | 34 +++++++++++++++----------------- firmware/export/lcd.h | 1 + 12 files changed, 154 insertions(+), 42 deletions(-) diff --git a/apps/gui/bitmap/list.c b/apps/gui/bitmap/list.c index 69cda9fa85..09a66f3386 100644 --- a/apps/gui/bitmap/list.c +++ b/apps/gui/bitmap/list.c @@ -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; inb_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); diff --git a/apps/gui/icon.c b/apps/gui/icon.c index 628196a98f..87ea0718fb 100644 --- a/apps/gui/icon.c +++ b/apps/gui/icon.c @@ -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); +} diff --git a/apps/gui/icon.h b/apps/gui/icon.h index e79defe798..ca7f04841d 100644 --- a/apps/gui/icon.h +++ b/apps/gui/icon.h @@ -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_*/ diff --git a/apps/gui/list.c b/apps/gui/list.c index 1a90ff9e40..66c3438574 100644 --- a/apps/gui/list.c +++ b/apps/gui/list.c @@ -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 diff --git a/apps/gui/viewport.c b/apps/gui/viewport.c index 2ab6c343ef..c5e44270d4 100644 --- a/apps/gui/viewport.c +++ b/apps/gui/viewport.c @@ -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 diff --git a/apps/gui/viewport.h b/apps/gui/viewport.h index 51ab35e575..3da001e190 100644 --- a/apps/gui/viewport.h +++ b/apps/gui/viewport.h @@ -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__ diff --git a/apps/lang/english.lang b/apps/lang/english.lang index 0e4d4bfc04..eb3c963512 100644 --- a/apps/lang/english.lang +++ b/apps/lang/english.lang @@ -12830,3 +12830,34 @@ multidrive_usb: "USB Hide Internal Drive" + + id: LANG_LIST_LINE_PADDING + desc: list padding, in display settings + user: core + + *: none + touchscreen: "Line Padding in Lists" + + + *: none + touchscreen: "Line Padding in Lists" + + + *: none + touchscreen: "Line Padding in Lists" + + + + id: LANG_AUTOMATIC + desc: generic automatic + user: core + + *: "Automatic" + + + *: "Automatic" + + + *: "Automatic" + + diff --git a/apps/menus/display_menu.c b/apps/menus/display_menu.c index 7e7b5a6903..957307d8a8 100644 --- a/apps/menus/display_menu.c +++ b/apps/menus/display_menu.c @@ -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 diff --git a/apps/settings.h b/apps/settings.h index 36e403be1b..927b17bf08 100644 --- a/apps/settings.h +++ b/apps/settings.h @@ -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 */ diff --git a/apps/settings_list.c b/apps/settings_list.c index eb62b9b975..a3d6587d0c 100644 --- a/apps/settings_list.c +++ b/apps/settings_list.c @@ -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 diff --git a/firmware/drivers/lcd-bitmap-common.c b/firmware/drivers/lcd-bitmap-common.c index fc84fdd6a1..8d95825858 100644 --- a/firmware/drivers/lcd-bitmap-common.c +++ b/firmware/drivers/lcd-bitmap-common.c @@ -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); } diff --git a/firmware/export/lcd.h b/firmware/export/lcd.h index e6e19b1597..56e19ddefa 100644 --- a/firmware/export/lcd.h +++ b/firmware/export/lcd.h @@ -43,6 +43,7 @@ struct viewport { #ifdef HAVE_LCD_BITMAP int flags; int font; + int line_height; int drawmode; #endif #if LCD_DEPTH > 1 -- cgit v1.2.3