diff options
Diffstat (limited to 'apps/gui/bitmap/list.c')
-rw-r--r-- | apps/gui/bitmap/list.c | 276 |
1 files changed, 276 insertions, 0 deletions
diff --git a/apps/gui/bitmap/list.c b/apps/gui/bitmap/list.c new file mode 100644 index 0000000000..63f24dd456 --- /dev/null +++ b/apps/gui/bitmap/list.c | |||
@@ -0,0 +1,276 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2007 by Jonathan Gordon | ||
11 | * | ||
12 | * All files in this archive are subject to the GNU General Public License. | ||
13 | * See the file COPYING in the source tree root for full license agreement. | ||
14 | * | ||
15 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
16 | * KIND, either express or implied. | ||
17 | * | ||
18 | ****************************************************************************/ | ||
19 | |||
20 | /* This file contains the code to draw the list widget on BITMAP LCDs. */ | ||
21 | |||
22 | #include "config.h" | ||
23 | #include "lcd.h" | ||
24 | #include "font.h" | ||
25 | #include "button.h" | ||
26 | #include "sprintf.h" | ||
27 | #include "string.h" | ||
28 | #include "settings.h" | ||
29 | #include "kernel.h" | ||
30 | #include "system.h" | ||
31 | |||
32 | #include "action.h" | ||
33 | #include "screen_access.h" | ||
34 | #include "list.h" | ||
35 | #include "scrollbar.h" | ||
36 | #include "statusbar.h" | ||
37 | #include "textarea.h" | ||
38 | #include "lang.h" | ||
39 | #include "sound.h" | ||
40 | #include "misc.h" | ||
41 | #include "talk.h" | ||
42 | #include "viewport.h" | ||
43 | |||
44 | #define SCROLLBAR_WIDTH 6 | ||
45 | #define ICON_PADDING 1 | ||
46 | |||
47 | /* globals */ | ||
48 | struct viewport title_text[NB_SCREENS], title_icons[NB_SCREENS], | ||
49 | list_text[NB_SCREENS], list_icons[NB_SCREENS]; | ||
50 | |||
51 | /* should probably be moved somewhere else */ | ||
52 | int list_title_height(struct gui_synclist *list, struct viewport *vp) | ||
53 | { | ||
54 | (void)list; | ||
55 | return font_get(vp->font)->height; | ||
56 | } | ||
57 | int gui_list_get_item_offset(struct gui_synclist * gui_list, int item_width, | ||
58 | int text_pos, struct screen * display, | ||
59 | struct viewport *vp); | ||
60 | bool list_display_title(struct gui_synclist *list, struct viewport *vp); | ||
61 | |||
62 | /* Draw the list... | ||
63 | internal screen layout: | ||
64 | ----------------- | ||
65 | |TI| title | TI is title icon | ||
66 | ----------------- | ||
67 | | | | | | ||
68 | |S|I| | S - scrollbar | ||
69 | | | | items | I - icons | ||
70 | | | | | | ||
71 | ------------------ | ||
72 | */ | ||
73 | static bool draw_title(struct screen *display, struct viewport *parent, | ||
74 | struct gui_synclist *list) | ||
75 | { | ||
76 | struct viewport *vp_icons = &title_icons[display->screen_type]; | ||
77 | struct viewport *vp_text = &title_text[display->screen_type]; | ||
78 | if (!list_display_title(list, parent)) | ||
79 | return false; | ||
80 | *vp_text = *parent; | ||
81 | vp_text->height = list_title_height(list, parent); | ||
82 | if (list->title_icon != Icon_NOICON && global_settings.show_icons) | ||
83 | { | ||
84 | *vp_icons = *vp_text; | ||
85 | vp_icons->width = get_icon_width(display->screen_type) | ||
86 | + ICON_PADDING*2; | ||
87 | vp_icons->x += ICON_PADDING; | ||
88 | |||
89 | vp_text->width -= vp_icons->width + vp_icons->x; | ||
90 | vp_text->x += vp_icons->width + vp_icons->x; | ||
91 | |||
92 | display->set_viewport(vp_icons); | ||
93 | screen_put_icon(display, 0, 0, list->title_icon); | ||
94 | } | ||
95 | display->set_viewport(vp_text); | ||
96 | vp_text->drawmode = STYLE_DEFAULT; | ||
97 | #ifdef HAVE_LCD_COLOR | ||
98 | if (list->title_color >= 0) | ||
99 | { | ||
100 | vp_text->drawmode |= (STYLE_COLORED|list->title_color);} | ||
101 | #endif | ||
102 | display->puts_scroll_style_offset(0, 0, list->title, | ||
103 | vp_text->drawmode, 0); | ||
104 | return true; | ||
105 | } | ||
106 | |||
107 | void list_draw(struct screen *display, struct viewport *parent, | ||
108 | struct gui_synclist *list) | ||
109 | { | ||
110 | int start, end, line_height, i; | ||
111 | int icon_width = get_icon_width(display->screen_type) + ICON_PADDING; | ||
112 | bool show_cursor = !global_settings.cursor_style && | ||
113 | list->show_selection_marker; | ||
114 | #ifdef HAVE_LCD_COLOR | ||
115 | unsigned char cur_line = 0; | ||
116 | #endif | ||
117 | int item_offset; | ||
118 | bool show_title; | ||
119 | line_height = font_get(parent->font)->height; | ||
120 | display->set_viewport(parent); | ||
121 | display->clear_viewport(); | ||
122 | display->stop_scroll(); | ||
123 | list_text[display->screen_type] = *parent; | ||
124 | if ((show_title = draw_title(display, parent, list))) | ||
125 | { | ||
126 | list_text[display->screen_type].y += list_title_height(list, parent); | ||
127 | list_text[display->screen_type].height -= list_title_height(list, parent); | ||
128 | } | ||
129 | |||
130 | start = list->start_item[display->screen_type]; | ||
131 | end = start + viewport_get_nb_lines(&list_text[display->screen_type]); | ||
132 | |||
133 | /* draw the scrollbar if its needed */ | ||
134 | if (global_settings.scrollbar && | ||
135 | viewport_get_nb_lines(&list_text[display->screen_type]) < list->nb_items) | ||
136 | { | ||
137 | struct viewport vp; | ||
138 | vp = list_text[display->screen_type]; | ||
139 | vp.width = SCROLLBAR_WIDTH; | ||
140 | list_text[display->screen_type].width -= SCROLLBAR_WIDTH; | ||
141 | list_text[display->screen_type].x += SCROLLBAR_WIDTH; | ||
142 | vp.height = line_height * | ||
143 | viewport_get_nb_lines(&list_text[display->screen_type]); | ||
144 | vp.x = parent->x; | ||
145 | display->set_viewport(&vp); | ||
146 | gui_scrollbar_draw(display, 0, 0, SCROLLBAR_WIDTH-1, | ||
147 | vp.height, list->nb_items, | ||
148 | list->start_item[display->screen_type], | ||
149 | list->start_item[display->screen_type] + end-start, | ||
150 | VERTICAL); | ||
151 | } | ||
152 | else if (show_title) | ||
153 | { | ||
154 | /* shift everything right a bit... */ | ||
155 | list_text[display->screen_type].width -= SCROLLBAR_WIDTH; | ||
156 | list_text[display->screen_type].x += SCROLLBAR_WIDTH; | ||
157 | } | ||
158 | |||
159 | /* setup icon placement */ | ||
160 | list_icons[display->screen_type] = list_text[display->screen_type]; | ||
161 | int icon_count = global_settings.show_icons && | ||
162 | (list->callback_get_item_icon != NULL) ? 1 : 0; | ||
163 | if (show_cursor) | ||
164 | icon_count++; | ||
165 | if (icon_count) | ||
166 | { | ||
167 | list_icons[display->screen_type].width = icon_width * icon_count; | ||
168 | list_text[display->screen_type].width -= | ||
169 | list_icons[display->screen_type].width + ICON_PADDING; | ||
170 | list_text[display->screen_type].x += | ||
171 | list_icons[display->screen_type].width + ICON_PADDING; | ||
172 | } | ||
173 | |||
174 | for (i=start; i<end && i<list->nb_items; i++) | ||
175 | { | ||
176 | /* do the text */ | ||
177 | unsigned char *s; | ||
178 | char entry_buffer[MAX_PATH]; | ||
179 | unsigned char *entry_name; | ||
180 | int text_pos = 0; | ||
181 | s = list->callback_get_item_name(i, list->data, entry_buffer); | ||
182 | entry_name = P2STR(s); | ||
183 | display->set_viewport(&list_text[display->screen_type]); | ||
184 | list_text[display->screen_type].drawmode = STYLE_DEFAULT; | ||
185 | /* position the string at the correct offset place */ | ||
186 | int item_width,h; | ||
187 | display->getstringsize(entry_name, &item_width, &h); | ||
188 | item_offset = gui_list_get_item_offset(list, item_width, | ||
189 | text_pos, display, | ||
190 | &list_text[display->screen_type]); | ||
191 | |||
192 | #ifdef HAVE_LCD_COLOR | ||
193 | /* if the list has a color callback */ | ||
194 | if (list->callback_get_item_color) | ||
195 | { | ||
196 | int color = list->callback_get_item_color(i, list->data); | ||
197 | /* if color selected */ | ||
198 | if (color >= 0) | ||
199 | { | ||
200 | list_text[display->screen_type].drawmode |= STYLE_COLORED|color; | ||
201 | } | ||
202 | } | ||
203 | #endif | ||
204 | |||
205 | if(list->show_selection_marker && global_settings.cursor_style && | ||
206 | i >= list->selected_item && | ||
207 | i < list->selected_item + list->selected_size) | ||
208 | {/* The selected item must be displayed scrolling */ | ||
209 | if (global_settings.cursor_style == 1 || display->depth < 16) | ||
210 | { | ||
211 | /* Display inverted-line-style */ | ||
212 | list_text[display->screen_type].drawmode |= STYLE_INVERT; | ||
213 | } | ||
214 | #ifdef HAVE_LCD_COLOR | ||
215 | else if (global_settings.cursor_style == 2) | ||
216 | { | ||
217 | /* Display colour line selector */ | ||
218 | list_text[display->screen_type].drawmode |= STYLE_COLORBAR; | ||
219 | } | ||
220 | else if (global_settings.cursor_style == 3) | ||
221 | { | ||
222 | /* Display gradient line selector */ | ||
223 | list_text[display->screen_type].drawmode = STYLE_GRADIENT; | ||
224 | |||
225 | /* Make the lcd driver know how many lines the gradient should | ||
226 | cover and current line number */ | ||
227 | /* number of selected lines */ | ||
228 | list_text[display->screen_type].drawmode |= NUMLN_PACK(list->selected_size); | ||
229 | /* current line number, zero based */ | ||
230 | list_text[display->screen_type].drawmode |= CURLN_PACK(cur_line); | ||
231 | cur_line++; | ||
232 | } | ||
233 | #endif | ||
234 | /* if the text is smaller than the viewport size */ | ||
235 | if (item_offset > item_width - (list_text[display->screen_type].width - text_pos)) | ||
236 | { | ||
237 | /* don't scroll */ | ||
238 | display->puts_style_offset(0, i-start, entry_name, | ||
239 | list_text[display->screen_type].drawmode, item_offset); | ||
240 | } | ||
241 | else | ||
242 | { | ||
243 | display->puts_scroll_style_offset(0, i-start, entry_name, | ||
244 | list_text[display->screen_type].drawmode, item_offset); | ||
245 | } | ||
246 | } | ||
247 | else | ||
248 | display->puts_style_offset(0, i-start, entry_name, | ||
249 | list_text[display->screen_type].drawmode, item_offset); | ||
250 | /* do the icon */ | ||
251 | if (list->callback_get_item_icon && global_settings.show_icons) | ||
252 | { | ||
253 | display->set_viewport(&list_icons[display->screen_type]); | ||
254 | screen_put_icon_with_offset(display, show_cursor?1:0, | ||
255 | (i-start),show_cursor?ICON_PADDING:0,0, | ||
256 | list->callback_get_item_icon(i, list->data)); | ||
257 | if (show_cursor && i >= list->selected_item && | ||
258 | i < list->selected_item + list->selected_size) | ||
259 | { | ||
260 | screen_put_icon(display, 0, i-start, Icon_Cursor); | ||
261 | } | ||
262 | } | ||
263 | else if (show_cursor && i >= list->selected_item && | ||
264 | i < list->selected_item + list->selected_size) | ||
265 | { | ||
266 | display->set_viewport(&list_icons[display->screen_type]); | ||
267 | screen_put_icon(display, 0, (i-start), Icon_Cursor); | ||
268 | } | ||
269 | } | ||
270 | |||
271 | display->set_viewport(parent); | ||
272 | display->update_viewport(); | ||
273 | display->set_viewport(NULL); | ||
274 | } | ||
275 | |||
276 | |||