2b59fc8489c64e0b9d889b46f8989cf18ecb51dd
1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2007 by Jonathan Gordon
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
22 /* This file contains the code to draw the list widget on BITMAP LCDs. */
35 #include "screen_access.h"
37 #include "scrollbar.h"
38 #include "statusbar.h"
45 #define SCROLLBAR_WIDTH 6
46 #define ICON_PADDING 1
48 static struct viewport title_text
[NB_SCREENS
], title_icons
[NB_SCREENS
],
49 list_text
[NB_SCREENS
], list_icons
[NB_SCREENS
];
51 /* should probably be moved somewhere else */
52 int list_title_height(struct gui_synclist
*list
, struct viewport
*vp
)
55 return font_get(vp
->font
)->height
;
57 int gui_list_get_item_offset(struct gui_synclist
* gui_list
, int item_width
,
58 int text_pos
, struct screen
* display
,
60 bool list_display_title(struct gui_synclist
*list
, struct viewport
*vp
);
63 internal screen layout:
65 |TI| title | TI is title icon
69 | | | items | I - icons
73 static bool draw_title(struct screen
*display
, struct viewport
*parent
,
74 struct gui_synclist
*list
)
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
))
81 vp_text
->height
= list_title_height(list
, parent
);
82 if (list
->title_icon
!= Icon_NOICON
&& global_settings
.show_icons
)
85 vp_icons
->width
= get_icon_width(display
->screen_type
)
87 vp_icons
->x
+= ICON_PADDING
;
89 vp_text
->width
-= vp_icons
->width
+ vp_icons
->x
;
90 vp_text
->x
+= vp_icons
->width
+ vp_icons
->x
;
92 display
->set_viewport(vp_icons
);
93 screen_put_icon(display
, 0, 0, list
->title_icon
);
95 display
->set_viewport(vp_text
);
96 vp_text
->drawmode
= STYLE_DEFAULT
;
98 if (list
->title_color
>= 0)
100 vp_text
->drawmode
|= (STYLE_COLORED
|list
->title_color
);}
102 display
->puts_scroll_style_offset(0, 0, list
->title
,
103 vp_text
->drawmode
, 0);
107 void list_draw(struct screen
*display
, struct viewport
*parent
,
108 struct gui_synclist
*list
)
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;
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
)))
126 list_text
[display
->screen_type
].y
+= list_title_height(list
, parent
);
127 list_text
[display
->screen_type
].height
-= list_title_height(list
, parent
);
130 start
= list
->start_item
[display
->screen_type
];
131 end
= start
+ viewport_get_nb_lines(&list_text
[display
->screen_type
]);
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
)
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
]);
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
,
154 /* shift everything right a bit... */
155 list_text
[display
->screen_type
].width
-= SCROLLBAR_WIDTH
;
156 list_text
[display
->screen_type
].x
+= SCROLLBAR_WIDTH
;
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;
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
;
174 for (i
=start
; i
<end
&& i
<list
->nb_items
; i
++)
178 char entry_buffer
[MAX_PATH
];
179 unsigned char *entry_name
;
181 s
= list
->callback_get_item_name(i
, list
->data
, entry_buffer
,
182 sizeof(entry_buffer
));
183 entry_name
= P2STR(s
);
184 display
->set_viewport(&list_text
[display
->screen_type
]);
185 list_text
[display
->screen_type
].drawmode
= STYLE_DEFAULT
;
186 /* position the string at the correct offset place */
188 display
->getstringsize(entry_name
, &item_width
, &h
);
189 item_offset
= gui_list_get_item_offset(list
, item_width
,
191 &list_text
[display
->screen_type
]);
193 #ifdef HAVE_LCD_COLOR
194 /* if the list has a color callback */
195 if (list
->callback_get_item_color
)
197 int color
= list
->callback_get_item_color(i
, list
->data
);
198 /* if color selected */
201 list_text
[display
->screen_type
].drawmode
|= STYLE_COLORED
|color
;
205 if(i
>= list
->selected_item
&&
206 i
< list
->selected_item
+ list
->selected_size
&& list
->show_selection_marker
)
207 {/* The selected item must be displayed scrolling */
208 if (global_settings
.cursor_style
== 1
209 #ifdef HAVE_REMOTE_LCD
210 /* the global_settings.cursor_style check is here to make sure
211 if they want the cursor instead of bar it will work */
212 || (display
->depth
< 16 && global_settings
.cursor_style
)
216 /* Display inverted-line-style */
217 list_text
[display
->screen_type
].drawmode
= STYLE_INVERT
;
219 #ifdef HAVE_LCD_COLOR
220 else if (global_settings
.cursor_style
== 2)
222 /* Display colour line selector */
223 list_text
[display
->screen_type
].drawmode
= STYLE_COLORBAR
;
225 else if (global_settings
.cursor_style
== 3)
227 /* Display gradient line selector */
228 list_text
[display
->screen_type
].drawmode
= STYLE_GRADIENT
;
230 /* Make the lcd driver know how many lines the gradient should
231 cover and current line number */
232 /* number of selected lines */
233 list_text
[display
->screen_type
].drawmode
|= NUMLN_PACK(list
->selected_size
);
234 /* current line number, zero based */
235 list_text
[display
->screen_type
].drawmode
|= CURLN_PACK(cur_line
);
239 /* if the text is smaller than the viewport size */
240 if (item_offset
> item_width
- (list_text
[display
->screen_type
].width
- text_pos
))
243 display
->puts_style_offset(0, i
-start
, entry_name
,
244 list_text
[display
->screen_type
].drawmode
, item_offset
);
248 display
->puts_scroll_style_offset(0, i
-start
, entry_name
,
249 list_text
[display
->screen_type
].drawmode
, item_offset
);
253 display
->puts_style_offset(0, i
-start
, entry_name
,
254 list_text
[display
->screen_type
].drawmode
, item_offset
);
256 if (list
->callback_get_item_icon
&& global_settings
.show_icons
)
258 display
->set_viewport(&list_icons
[display
->screen_type
]);
259 screen_put_icon_with_offset(display
, show_cursor
?1:0,
260 (i
-start
),show_cursor
?ICON_PADDING
:0,0,
261 list
->callback_get_item_icon(i
, list
->data
));
262 if (show_cursor
&& i
>= list
->selected_item
&&
263 i
< list
->selected_item
+ list
->selected_size
)
265 screen_put_icon(display
, 0, i
-start
, Icon_Cursor
);
268 else if (show_cursor
&& i
>= list
->selected_item
&&
269 i
< list
->selected_item
+ list
->selected_size
)
271 display
->set_viewport(&list_icons
[display
->screen_type
]);
272 screen_put_icon(display
, 0, (i
-start
), Icon_Cursor
);
276 display
->set_viewport(parent
);
277 display
->update_viewport();
278 display
->set_viewport(NULL
);
282 #if defined(HAVE_TOUCHPAD)
283 /* This needs to be fixed if we ever get more than 1 touchscreen on a target.
284 * This also assumes the whole screen is used, which is a bad assumption but
285 * fine until customizable lists comes in...
287 static bool scrolling
=false;
289 unsigned gui_synclist_do_touchpad(struct gui_synclist
* gui_list
, struct viewport
*parent
)
292 unsigned button
= action_get_touchpad_press(&x
, &y
);
294 struct screen
*display
= &screens
[SCREEN_MAIN
];
295 if (button
== BUTTON_NONE
)
297 if (x
<list_text
[SCREEN_MAIN
].x
)
299 /* Top left corner is hopefully GO_TO_ROOT */
300 if (y
<list_text
[SCREEN_MAIN
].y
)
302 if (button
== BUTTON_REL
)
303 return ACTION_STD_MENU
;
304 else if (button
== (BUTTON_REPEAT
|BUTTON_REL
))
305 return ACTION_STD_CONTEXT
;
312 int new_selection
, nb_lines
;
314 nb_lines
= viewport_get_nb_lines(&list_text
[SCREEN_MAIN
]);
315 if (nb_lines
< gui_list
->nb_items
)
317 height
= nb_lines
* font_get(parent
->font
)->height
;
318 size
= height
/ gui_list
->nb_items
;
319 new_selection
= ((y
-list_text
[SCREEN_MAIN
].y
)*(gui_list
->nb_items
-nb_lines
))/(height
-size
);
321 if (new_selection
- gui_list
->start_item
[SCREEN_MAIN
] > (nb_lines
/2))
322 new_selection
= gui_list
->start_item
[SCREEN_MAIN
]+(nb_lines
/2);
323 else if (new_selection
> gui_list
->nb_items
-nb_lines
)
324 new_selection
= gui_list
->nb_items
-nb_lines
;
326 gui_synclist_select_item(gui_list
, new_selection
);
327 gui_list
->start_item
[SCREEN_MAIN
] = new_selection
;
328 return ACTION_REDRAW
;
334 /* |--------------------------------------------------------|
335 * | Description of the touchscreen list interface: |
336 * |--------------------------------------------------------|
337 * | Pressing an item will select it and "enter" it. |
339 * | Pressing and holding your pen down will scroll through |
340 * | the list of items. |
342 * | Pressing and holding your pen down on a single item |
343 * | will bring up the context menu of it. |
344 * |--------------------------------------------------------|
346 if (y
> list_text
[SCREEN_MAIN
].y
)
348 int line_height
, actual_y
;
350 actual_y
= y
- list_text
[SCREEN_MAIN
].y
;
351 line_height
= font_get(parent
->font
)->height
;
352 line
= actual_y
/ line_height
;
354 if(actual_y
%line_height
== 0) /* Pressed a border */
357 if(actual_y
>= line_height
*gui_list
->nb_items
) /* Pressed below the list */
360 if (line
!= gui_list
->selected_item
- gui_list
->start_item
[SCREEN_MAIN
] && button
^ BUTTON_REL
)
362 if (gui_list
->start_item
[SCREEN_MAIN
]+line
> gui_list
->nb_items
)
364 if(button
& BUTTON_REPEAT
)
366 gui_synclist_select_item(gui_list
, gui_list
->start_item
[SCREEN_MAIN
]+line
);
367 return ACTION_REDRAW
;
370 if (button
== (BUTTON_REPEAT
|BUTTON_REL
))
374 /* Pen was hold on the same line as the previously selected one
375 * => simulate long button press
377 return ACTION_STD_CONTEXT
;
381 /* Pen was moved across several lines and then released on this one
388 else if(button
== BUTTON_REL
)
390 /* Pen was released on either the same line as the previously selected one
392 * => simulate short press
394 return ACTION_STD_OK
;
399 /* Title goes up one level (only on BUTTON_REL&~BUTTON_REPEAT) */
400 else if (y
> title_text
[SCREEN_MAIN
].y
&& draw_title(display
, parent
, gui_list
) && button
== BUTTON_REL
)
401 return ACTION_STD_CANCEL
;
402 /* Title or statusbar is cancel (only on BUTTON_REL&~BUTTON_REPEAT) */
403 else if (global_settings
.statusbar
&& button
== BUTTON_REL
)
404 return ACTION_STD_CANCEL
;