summaryrefslogtreecommitdiff
path: root/apps/gui/list.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/gui/list.c')
-rw-r--r--apps/gui/list.c413
1 files changed, 72 insertions, 341 deletions
diff --git a/apps/gui/list.c b/apps/gui/list.c
index bc21976..fbc417e 100644
--- a/apps/gui/list.c
+++ b/apps/gui/list.c
@@ -37,6 +37,7 @@
#include "sound.h"
#include "misc.h"
#include "talk.h"
+#include "viewport.h"
#ifdef HAVE_LCD_CHARCELLS
#define SCROLL_LIMIT 1
@@ -56,11 +57,46 @@ static bool offset_out_of_view = false;
#endif
static struct gui_synclist* last_list_displayed;
-#define SHOW_LIST_TITLE ((gui_list->title != NULL) && \
- (display->nb_lines > 2))
-
static void gui_list_select_at_offset(struct gui_synclist * gui_list,
int offset);
+void list_draw(struct screen *display, struct viewport *parent, struct gui_synclist *list);
+
+#ifdef HAVE_LCD_BITMAP
+static struct viewport parent[NB_SCREENS];
+void list_init_viewports(void)
+{
+ int i;
+ struct viewport *vp;
+ FOR_NB_SCREENS(i)
+ {
+ vp = &parent[i];
+ viewport_set_defaults(vp, i);
+ }
+}
+#else
+static struct viewport parent[NB_SCREENS] =
+{
+ [SCREEN_MAIN] =
+ {
+ .x = 0,
+ .y = 0,
+ .width = LCD_WIDTH,
+ .height = LCD_HEIGHT
+ },
+};
+void list_init_viewports(void)
+{
+}
+#endif
+
+#ifdef HAVE_LCD_BITMAP
+bool list_display_title(struct gui_synclist *list, struct viewport *vp)
+{
+ return list->title != NULL && viewport_get_nb_lines(vp)>2;
+}
+#else
+#define list_display_title(l,v) false
+#endif
/*
* Initializes a scrolling list
@@ -82,7 +118,7 @@ void gui_synclist_init(struct gui_synclist * gui_list,
gui_list->callback_get_item_icon = NULL;
gui_list->callback_get_item_name = callback_get_item_name;
gui_list->callback_speak_item = NULL;
- gui_list_set_nb_items(gui_list, 0);
+ gui_list->nb_items = 0;
gui_list->selected_item = 0;
FOR_NB_SCREENS(i)
{
@@ -91,6 +127,7 @@ void gui_synclist_init(struct gui_synclist * gui_list,
#ifdef HAVE_LCD_BITMAP
gui_list->offset_position[i] = 0;
#endif
+ gui_list->parent[i] = &parent[i];
}
gui_list->limit_scroll = false;
gui_list->data=data;
@@ -118,8 +155,10 @@ void gui_synclist_hide_selection_marker(struct gui_synclist * lists, bool hide)
#ifdef HAVE_LCD_BITMAP
-static int gui_list_get_item_offset(struct gui_synclist * gui_list, int item_width,
- int text_pos, struct screen * display)
+int list_title_height(struct gui_synclist *list, struct viewport *vp);
+
+int gui_list_get_item_offset(struct gui_synclist * gui_list, int item_width,
+ int text_pos, struct screen * display, struct viewport *vp)
{
int item_offset;
@@ -130,7 +169,7 @@ static int gui_list_get_item_offset(struct gui_synclist * gui_list, int item_wid
else
{
/* if text is smaller then view */
- if (item_width <= display->width - text_pos)
+ if (item_width <= vp->width - text_pos)
{
item_offset = 0;
}
@@ -138,8 +177,8 @@ static int gui_list_get_item_offset(struct gui_synclist * gui_list, int item_wid
{
/* if text got out of view */
if (gui_list->offset_position[display->screen_type] >
- item_width - (display->width - text_pos))
- item_offset = item_width - (display->width - text_pos);
+ item_width - (vp->width - text_pos))
+ item_offset = item_width - (vp->width - text_pos);
else
item_offset = gui_list->offset_position[display->screen_type];
}
@@ -148,341 +187,32 @@ static int gui_list_get_item_offset(struct gui_synclist * gui_list, int item_wid
return item_offset;
}
#endif
-
-/*
- * Draws the list on the attached screen
- * - gui_list : the list structure
- */
-static void gui_list_draw_smart(struct gui_synclist *gui_list, struct screen * display)
-{
- int text_pos;
- bool draw_icons = (gui_list->callback_get_item_icon != NULL && global_settings.show_icons);
- bool draw_cursor;
- int i;
- int lines;
- static int last_lines[NB_SCREENS] = {0};
-#ifdef HAVE_LCD_BITMAP
- int item_offset;
- int old_margin = display->getxmargin();
-#endif
- int start, end;
- bool partial_draw = false;
-
-#ifdef HAVE_LCD_BITMAP
- display->setfont(FONT_UI);
- gui_textarea_update_nblines(display);
-#endif
- /* Speed up UI by drawing the changed contents only. */
- if (gui_list == last_list_displayed
- && gui_list->last_displayed_start_item[display->screen_type] == gui_list->start_item[display->screen_type]
- && gui_list->selected_size == 1)
- {
- partial_draw = true;
- }
-
- lines = display->nb_lines - SHOW_LIST_TITLE;
- if (last_lines[display->screen_type] != lines)
- {
- gui_list_select_at_offset(gui_list, 0);
- last_lines[display->screen_type] = lines;
- }
-
- if (partial_draw)
- {
- end = gui_list->last_displayed_selected_item - gui_list->start_item[display->screen_type];
- i = gui_list->selected_item - gui_list->start_item[display->screen_type];
- if (i < end )
- {
- start = i;
- end++;
- }
- else
- {
- start = end;
- end = i + 1;
- }
- }
- else
- {
- gui_textarea_clear(display);
- start = 0;
- end = display->nb_lines;
- gui_list->last_displayed_start_item[display->screen_type] = gui_list->start_item[display->screen_type];
- last_list_displayed = gui_list;
- }
-
- gui_list->last_displayed_selected_item = gui_list->selected_item;
-
- /* position and draw the list title & icon */
- if (SHOW_LIST_TITLE && !partial_draw)
- {
- if (gui_list->title_icon != NOICON && draw_icons)
- {
- screen_put_icon(display, 0, 0, gui_list->title_icon);
-#ifdef HAVE_LCD_BITMAP
- text_pos = get_icon_width(display->screen_type)+2; /* pixels */
-#else
- text_pos = 1; /* chars */
-#endif
- }
- else
- {
- text_pos = 0;
- }
-
-#ifdef HAVE_LCD_BITMAP
- int title_style = STYLE_DEFAULT;
-#ifdef HAVE_LCD_COLOR
- if (gui_list->title_color >= 0)
- {
- title_style |= STYLE_COLORED;
- title_style |= gui_list->title_color;
- }
-#endif
- screen_set_xmargin(display, text_pos); /* margin for title */
- item_offset = gui_list_get_item_offset(gui_list, gui_list->title_width,
- text_pos, display);
- if (item_offset > gui_list->title_width - (display->width - text_pos))
- display->puts_style_offset(0, 0, gui_list->title,
- title_style, item_offset);
- else
- display->puts_scroll_style_offset(0, 0, gui_list->title,
- title_style, item_offset);
-#else
- display->puts_scroll(text_pos, 0, gui_list->title);
-#endif
- }
-
- /* Adjust the position of icon, cursor, text for the list */
-#ifdef HAVE_LCD_BITMAP
- gui_textarea_update_nblines(display);
- bool draw_scrollbar;
-
- draw_scrollbar = (global_settings.scrollbar &&
- lines < gui_list->nb_items);
-
- draw_cursor = !global_settings.cursor_style &&
- gui_list->show_selection_marker;
- text_pos = 0; /* here it's in pixels */
- if(draw_scrollbar || SHOW_LIST_TITLE) /* indent if there's
- a title */
- {
- text_pos += SCROLLBAR_WIDTH;
- }
- if(draw_cursor)
- text_pos += get_icon_width(display->screen_type) + 2;
-
- if(draw_icons)
- text_pos += get_icon_width(display->screen_type) + 2;
-#else
- draw_cursor = true;
- if(draw_icons)
- text_pos = 2; /* here it's in chars */
- else
- text_pos = 1;
-#endif
-
-#ifdef HAVE_LCD_BITMAP
- screen_set_xmargin(display, text_pos); /* margin for list */
-#endif
-
- if (SHOW_LIST_TITLE)
- {
- start++;
- if (end < display->nb_lines)
- end++;
- }
-
-#ifdef HAVE_LCD_COLOR
- unsigned char cur_line = 0;
-#endif
- for (i = start; i < end; i++)
- {
- unsigned char *s;
- char entry_buffer[MAX_PATH];
- unsigned char *entry_name;
- int current_item = gui_list->start_item[display->screen_type] +
- (SHOW_LIST_TITLE ? i-1 : i);
-
- /* When there are less items to display than the
- * current available space on the screen, we stop*/
- if(current_item >= gui_list->nb_items)
- break;
- s = gui_list->callback_get_item_name(current_item,
- gui_list->data,
- entry_buffer);
- entry_name = P2STR(s);
-
-#ifdef HAVE_LCD_BITMAP
- int style = STYLE_DEFAULT;
- /* position the string at the correct offset place */
- int item_width,h;
- display->getstringsize(entry_name, &item_width, &h);
- item_offset = gui_list_get_item_offset(gui_list, item_width,
- text_pos, display);
-#endif
-
-#ifdef HAVE_LCD_COLOR
- /* if the list has a color callback */
- if (gui_list->callback_get_item_color)
- {
- int color = gui_list->callback_get_item_color(current_item,
- gui_list->data);
- /* if color selected */
- if (color >= 0)
- {
- style |= STYLE_COLORED;
- style |= color;
- }
- }
-#endif
-
- if(gui_list->show_selection_marker &&
- current_item >= gui_list->selected_item &&
- current_item < gui_list->selected_item + gui_list->selected_size)
- {/* The selected item must be displayed scrolling */
-#ifdef HAVE_LCD_BITMAP
- if (global_settings.cursor_style == 1
-#ifdef HAVE_REMOTE_LCD
- || display->screen_type == SCREEN_REMOTE
-#endif
- )
- {
- /* Display inverted-line-style */
- style |= STYLE_INVERT;
- }
-#ifdef HAVE_LCD_COLOR
- else if (global_settings.cursor_style == 2)
- {
- /* Display colour line selector */
- style |= STYLE_COLORBAR;
- }
- else if (global_settings.cursor_style == 3)
- {
- /* Display gradient line selector */
- style = STYLE_GRADIENT;
-
- /* Make the lcd driver know how many lines the gradient should
- cover and current line number */
- /* number of selected lines */
- style |= NUMLN_PACK(gui_list->selected_size);
- /* current line number, zero based */
- style |= CURLN_PACK(cur_line);
- cur_line++;
- }
-#endif
- else /* if (!global_settings.cursor_style) */
- {
- if (current_item % gui_list->selected_size != 0)
- draw_cursor = false;
- }
- /* if the text is smaller than the viewport size */
- if (item_offset > item_width - (display->width - text_pos))
- {
- /* don't scroll */
- display->puts_style_offset(0, i, entry_name,
- style, item_offset);
- }
- else
- {
- display->puts_scroll_style_offset(0, i, entry_name,
- style, item_offset);
- }
-#else
- display->puts_scroll(text_pos, i, entry_name);
-#endif
-
- if (draw_cursor)
- {
- screen_put_icon_with_offset(display, 0, i,
- (draw_scrollbar || SHOW_LIST_TITLE)?
- SCROLLBAR_WIDTH: 0,
- 0, Icon_Cursor);
- }
- }
- else
- {/* normal item */
- if(gui_list->scroll_all)
- {
-#ifdef HAVE_LCD_BITMAP
- display->puts_scroll_style_offset(0, i, entry_name,
- style, item_offset);
-#else
- display->puts_scroll(text_pos, i, entry_name);
-#endif
- }
- else
- {
-#ifdef HAVE_LCD_BITMAP
- display->puts_style_offset(0, i, entry_name,
- style, item_offset);
-#else
- display->puts(text_pos, i, entry_name);
-#endif
- }
- }
- /* Icons display */
- if(draw_icons)
- {
- enum themable_icons icon;
- icon = gui_list->callback_get_item_icon(current_item, gui_list->data);
- if(icon > Icon_NOICON)
- {
-#ifdef HAVE_LCD_BITMAP
- int x = draw_cursor?1:0;
- int x_off = (draw_scrollbar || SHOW_LIST_TITLE) ? SCROLLBAR_WIDTH: 0;
- screen_put_icon_with_offset(display, x, i,
- x_off, 0, icon);
-#else
- screen_put_icon(display, 1, i, icon);
-#endif
- }
- }
- }
-
-#ifdef HAVE_LCD_BITMAP
- /* Draw the scrollbar if needed*/
- if(draw_scrollbar)
- {
- int y_start = gui_textarea_get_ystart(display);
- if (SHOW_LIST_TITLE)
- y_start += display->char_height;
- int scrollbar_y_end = display->char_height *
- lines + y_start;
- gui_scrollbar_draw(display, 0, y_start, SCROLLBAR_WIDTH-1,
- scrollbar_y_end - y_start, gui_list->nb_items,
- gui_list->start_item[display->screen_type],
- gui_list->start_item[display->screen_type] + lines, VERTICAL);
- }
-
- screen_set_xmargin(display, old_margin);
-#endif
-
- gui_textarea_update(display);
-}
-
/*
* Force a full screen update.
*/
+
void gui_synclist_draw(struct gui_synclist *gui_list)
{
int i;
FOR_NB_SCREENS(i)
{
last_list_displayed = NULL;
- gui_list_draw_smart(gui_list, &screens[i]);
+ list_draw(&screens[i], gui_list->parent[i], gui_list);
}
}
-
-
/* sets up the list so the selection is shown correctly on the screen */
static void gui_list_put_selection_on_screen(struct gui_synclist * gui_list,
enum screen_type screen)
{
- struct screen *display = &screens[screen];
- int nb_lines = display->nb_lines - SHOW_LIST_TITLE;
+ int nb_lines;
int difference = gui_list->selected_item - gui_list->start_item[screen];
+ struct viewport vp = *gui_list->parent[screen];
+#ifdef HAVE_LCD_BITMAP
+ if (list_display_title(gui_list, gui_list->parent[screen]))
+ vp.height -= list_title_height(gui_list,gui_list->parent[screen]);
+#endif
+ nb_lines = viewport_get_nb_lines(&vp);
/* edge case,, selected last item */
if (gui_list->selected_item == gui_list->nb_items -1)
@@ -576,8 +306,12 @@ static void gui_list_select_at_offset(struct gui_synclist * gui_list,
int i, nb_lines, screen_top;
FOR_NB_SCREENS(i)
{
- struct screen *display = &screens[i];
- nb_lines = display->nb_lines - SHOW_LIST_TITLE;
+ struct viewport vp = *gui_list->parent[i];
+#ifdef HAVE_LCD_BITMAP
+ if (list_display_title(gui_list, gui_list->parent[i]))
+ vp.height -= list_title_height(gui_list,gui_list->parent[i]);
+#endif
+ nb_lines = viewport_get_nb_lines(&vp);
if (offset > 0)
{
screen_top = gui_list->nb_items-nb_lines;
@@ -616,23 +350,12 @@ void gui_synclist_add_item(struct gui_synclist * gui_list)
*/
void gui_synclist_del_item(struct gui_synclist * gui_list)
{
- int i;
if(gui_list->nb_items > 0)
{
if (gui_list->selected_item == gui_list->nb_items-1)
gui_list->selected_item--;
- FOR_NB_SCREENS(i)
- {
- gui_textarea_update_nblines(&screens[i]);
- int nb_lines = screens[i].nb_lines;
- int dist_start_from_end = gui_list->nb_items
- - gui_list->start_item[i] - 1;
-
- /* scroll the list if needed */
- if( (dist_start_from_end < nb_lines) && (gui_list->start_item[i] != 0) )
- gui_list->start_item[i]--;
- }
gui_list->nb_items--;
+ gui_synclist_select_item(gui_list, gui_list->selected_item);
}
}
@@ -707,6 +430,14 @@ void gui_synclist_set_voice_callback(struct gui_synclist * lists,
lists->callback_speak_item = voice_callback;
}
+#ifdef HAVE_LCD_COLOR
+void gui_synclist_set_color_callback(struct gui_synclist * lists,
+ list_get_color color_callback)
+{
+ lists->callback_get_item_color = color_callback;
+}
+#endif
+
static void gui_synclist_select_next_page(struct gui_synclist * lists,
enum screen_type screen)
{