summaryrefslogtreecommitdiff
path: root/apps/gui
diff options
context:
space:
mode:
Diffstat (limited to 'apps/gui')
-rw-r--r--apps/gui/bitmap/list.c181
-rw-r--r--apps/gui/list.h5
2 files changed, 127 insertions, 59 deletions
diff --git a/apps/gui/bitmap/list.c b/apps/gui/bitmap/list.c
index 87d7107950..d892bff22b 100644
--- a/apps/gui/bitmap/list.c
+++ b/apps/gui/bitmap/list.c
@@ -40,6 +40,7 @@
40#include "misc.h" 40#include "misc.h"
41#include "viewport.h" 41#include "viewport.h"
42#include "statusbar-skinned.h" 42#include "statusbar-skinned.h"
43#include "debug.h"
43 44
44#define ICON_PADDING 1 45#define ICON_PADDING 1
45 46
@@ -230,8 +231,10 @@ void list_draw(struct screen *display, struct gui_synclist *list)
230 } 231 }
231 } 232 }
232#endif 233#endif
233 if(i >= list->selected_item && i < list->selected_item 234 /* draw the selected line */
234 + list->selected_size && list->show_selection_marker) 235 if(!list->hide_selection && i >= list->selected_item
236 && i < list->selected_item + list->selected_size
237 && list->show_selection_marker)
235 {/* The selected item must be displayed scrolling */ 238 {/* The selected item must be displayed scrolling */
236 if (global_settings.cursor_style == 1 239 if (global_settings.cursor_style == 1
237#ifdef HAVE_REMOTE_LCD 240#ifdef HAVE_REMOTE_LCD
@@ -308,7 +311,20 @@ void list_draw(struct screen *display, struct gui_synclist *list)
308 311
309#if defined(HAVE_TOUCHSCREEN) 312#if defined(HAVE_TOUCHSCREEN)
310/* This needs to be fixed if we ever get more than 1 touchscreen on a target. */ 313/* This needs to be fixed if we ever get more than 1 touchscreen on a target. */
311static bool scrolling=false; 314static enum {
315 SCROLL_NONE, /* no scrolling */
316 SCROLL_BAR, /* scroll by using the scrollbar */
317 SCROLL_SWIPE, /* scroll by wiping over the screen */
318} scroll_mode;
319
320static bool released = false;
321
322/* Used for kinetic scrolling as we need to know the last position to
323 * recognize the scroll direction.
324 * This gets reset to 0 at the end of scrolling
325 */
326static int last_position=0;
327
312 328
313static int gui_synclist_touchscreen_scrollbar(struct gui_synclist * gui_list, 329static int gui_synclist_touchscreen_scrollbar(struct gui_synclist * gui_list,
314 int y) 330 int y)
@@ -318,8 +334,7 @@ static int gui_synclist_touchscreen_scrollbar(struct gui_synclist * gui_list,
318 334
319 if (nb_lines < gui_list->nb_items) 335 if (nb_lines < gui_list->nb_items)
320 { 336 {
321 scrolling = true; 337 scroll_mode = SCROLL_BAR;
322
323 int scrollbar_size = nb_lines* 338 int scrollbar_size = nb_lines*
324 font_get(gui_list->parent[screen]->font)->height; 339 font_get(gui_list->parent[screen]->font)->height;
325 int actual_y = y - list_text[screen].y; 340 int actual_y = y - list_text[screen].y;
@@ -334,7 +349,6 @@ static int gui_synclist_touchscreen_scrollbar(struct gui_synclist * gui_list,
334 start_item = gui_list->nb_items - nb_lines; 349 start_item = gui_list->nb_items - nb_lines;
335 350
336 gui_list->start_item[screen] = start_item; 351 gui_list->start_item[screen] = start_item;
337 gui_synclist_select_item(gui_list, new_selection);
338 352
339 return ACTION_REDRAW; 353 return ACTION_REDRAW;
340 } 354 }
@@ -342,16 +356,44 @@ static int gui_synclist_touchscreen_scrollbar(struct gui_synclist * gui_list,
342 return ACTION_NONE; 356 return ACTION_NONE;
343} 357}
344 358
359/*
360 * returns the number of scrolled items since the last call
361 **/
362static int gui_synclist_touchscreen_scrolling(struct gui_synclist * gui_list, int position)
363{
364 const int screen = screens[SCREEN_MAIN].screen_type;
365 const int difference = position - last_position;
366 const int nb_lines = viewport_get_nb_lines(&list_text[screen]);
367 if(nb_lines < gui_list->nb_items && difference != 0) // only scroll if needed
368 {
369 int new_start_item;
370 new_start_item = gui_list->start_item[screen] - difference;
371 // check if new_start_item is bigger than list item count
372 if(new_start_item > gui_list->nb_items - nb_lines)
373 new_start_item = gui_list->nb_items - nb_lines;
374 // set new_start_item to 0 if it's negative
375 if(new_start_item < 0)
376 new_start_item = 0;
377 gui_list->start_item[screen] = new_start_item;
378 }
379 return difference;
380}
381
345unsigned gui_synclist_do_touchscreen(struct gui_synclist * gui_list) 382unsigned gui_synclist_do_touchscreen(struct gui_synclist * gui_list)
346{ 383{
347 short x, y; 384 short x, y;
348 const int button = action_get_touchscreen_press(&x, &y); 385 const int button = action_get_touchscreen_press(&x, &y);
349 int line;
350 const int screen = SCREEN_MAIN; 386 const int screen = SCREEN_MAIN;
351 const int list_start_item = gui_list->start_item[screen]; 387 const int list_start_item = gui_list->start_item[screen];
352 const struct viewport *list_text_vp = &list_text[screen]; 388 const struct viewport *list_text_vp = &list_text[screen];
353 int list_width = list_text_vp->width; 389 const bool old_released = released;
390 int line, list_width = list_text_vp->width;
391
392 released = (button&BUTTON_REL) != 0;
393 gui_list->hide_selection = (scroll_mode != SCROLL_NONE);
394
354 395
396
355 if (global_settings.scrollbar == SCROLLBAR_RIGHT) 397 if (global_settings.scrollbar == SCROLLBAR_RIGHT)
356 list_width += SCROLLBAR_WIDTH; 398 list_width += SCROLLBAR_WIDTH;
357 399
@@ -364,7 +406,7 @@ unsigned gui_synclist_do_touchscreen(struct gui_synclist * gui_list)
364 /* make sure it is inside the UI viewport */ 406 /* make sure it is inside the UI viewport */
365 if (list_display_title(gui_list, screen) && 407 if (list_display_title(gui_list, screen) &&
366 viewport_point_within_vp(&title_text[screen], x, y) && 408 viewport_point_within_vp(&title_text[screen], x, y) &&
367 button == BUTTON_REL) 409 button == BUTTON_REL && scroll_mode == SCROLL_NONE)
368 return ACTION_STD_CANCEL; 410 return ACTION_STD_CANCEL;
369 411
370 if (x < list_text_vp->x) 412 if (x < list_text_vp->x)
@@ -385,9 +427,26 @@ unsigned gui_synclist_do_touchscreen(struct gui_synclist * gui_list)
385 } 427 }
386 else 428 else
387 { 429 {
388 if (x > list_text_vp->x + list_text_vp->width && 430 int line_height = font_get(gui_list->parent[screen]->font)->height;
389 global_settings.scrollbar == SCROLLBAR_RIGHT) 431 /* add a small margin to prevent accidental selection */
432 int x_end = list_text_vp->x + list_text_vp->width - line_height;
433
434 /* conditions for scrollbar scrolling:
435 * * pen is on the scrollbar (x > x_end-scrollbar width)
436 * AND scrollbar is on the right (left case is handled above)
437 * OR * pen is in the somewhere else but we did scrollbar scrolling before
438 *
439 * scrollbar scrolling must end if the pen is released
440 * scrollbar scrolling must not happen if we're currently scrolling
441 * via swiping the screen
442 **/
443
444 if (!released && scroll_mode != SCROLL_SWIPE
445 && ((scroll_mode == SCROLL_BAR
446 || (x > x_end && global_settings.scrollbar == SCROLLBAR_RIGHT))))
447 {
390 return gui_synclist_touchscreen_scrollbar(gui_list, y); 448 return gui_synclist_touchscreen_scrollbar(gui_list, y);
449 }
391 450
392 /* |--------------------------------------------------------| 451 /* |--------------------------------------------------------|
393 * | Description of the touchscreen list interface: | 452 * | Description of the touchscreen list interface: |
@@ -403,10 +462,9 @@ unsigned gui_synclist_do_touchscreen(struct gui_synclist * gui_list)
403 */ 462 */
404 if (y > list_text_vp->y || button & BUTTON_REPEAT) 463 if (y > list_text_vp->y || button & BUTTON_REPEAT)
405 { 464 {
406 int line_height, actual_y; 465 int actual_y;
407 466
408 actual_y = y - list_text_vp->y; 467 actual_y = y - list_text_vp->y;
409 line_height = font_get(gui_list->parent[screen]->font)->height;
410 line = actual_y / line_height; 468 line = actual_y / line_height;
411 469
412 /* Pressed below the list*/ 470 /* Pressed below the list*/
@@ -416,59 +474,66 @@ unsigned gui_synclist_do_touchscreen(struct gui_synclist * gui_list)
416 /* Pressed a border */ 474 /* Pressed a border */
417 if(UNLIKELY(actual_y % line_height == 0)) 475 if(UNLIKELY(actual_y % line_height == 0))
418 return ACTION_NONE; 476 return ACTION_NONE;
419 477
420 if (line != (gui_list->selected_item - list_start_item) 478 if (released)
421 && button ^ BUTTON_REL)
422 {
423 if(button & BUTTON_REPEAT)
424 scrolling = true;
425
426 gui_synclist_select_item(gui_list, list_start_item + line);
427
428 return ACTION_REDRAW;
429 }
430
431 /* This has the same effect as the icons do when the scrollbar
432 is on the left (ie eliminate the chances an user enters/starts
433 an item when he wanted to use the scrollbar, due to touchscreen
434 dead zones)
435 */
436 if(global_settings.scrollbar == SCROLLBAR_RIGHT &&
437 x > list_text_vp->x + list_text_vp->width -
438 get_icon_width(SCREEN_MAIN))
439 return ACTION_NONE;
440
441 if (button == (BUTTON_REPEAT|BUTTON_REL))
442 { 479 {
443 if(!scrolling) 480 /* Pen was released anywhere on the screen */
481 last_position = 0;
482 if (scroll_mode == SCROLL_NONE)
444 { 483 {
445 /* Pen was hold on the same line as the 484 gui_synclist_select_item(gui_list, list_start_item + line);
446 * previously selected one 485 /* If BUTTON_REPEAT is set, then the pen was hold on
447 * => simulate long button press 486 * the same line for some time
448 */ 487 * -> context menu
449 return ACTION_STD_CONTEXT; 488 * otherwise,
489 * -> select
490 **/
491 if (button & BUTTON_REPEAT)
492 return ACTION_STD_CONTEXT;
493 return ACTION_STD_OK;
450 } 494 }
451 else 495 else
452 { 496 {
453 /* Pen was moved across several lines and then released on 497 /* we were scrolling
454 * this one 498 * -> reset scrolling but do nothing else */
455 * => do nothing 499 scroll_mode = SCROLL_NONE;
456 */
457 scrolling = false;
458 return ACTION_NONE; 500 return ACTION_NONE;
459 } 501 }
460 } 502 }
461 else if(button == BUTTON_REL &&
462 line == gui_list->selected_item - list_start_item)
463 {
464 /* Pen was released on either the same line as the previously
465 * selected one or an other one
466 * => simulate short press
467 */
468 return ACTION_STD_OK;
469 }
470 else 503 else
471 return ACTION_NONE; 504 { /* pen is on the screen */
505 int result = 0;
506 bool redraw = false;
507
508 /* beginning of list interaction denoted by release in
509 * the previous call */
510 if (old_released)
511 {
512 scroll_mode = SCROLL_NONE;
513 redraw = true;
514 /* don't draw the selection during scrolling */
515 gui_list->hide_selection = false;
516 }
517
518 /* select current item */
519 gui_synclist_select_item(gui_list, list_start_item+line);
520 if (last_position == 0)
521 last_position = line;
522 else
523 result = gui_synclist_touchscreen_scrolling(gui_list, line);
524
525 /* Start scrolling once the pen is moved without
526 * releasing it inbetween */
527 if (result)
528 {
529 redraw = true;
530 scroll_mode = SCROLL_SWIPE;
531 }
532
533 last_position = line;
534
535 return redraw ? ACTION_REDRAW:ACTION_NONE;
536 }
472 } 537 }
473 } 538 }
474 return ACTION_NONE; 539 return ACTION_NONE;
diff --git a/apps/gui/list.h b/apps/gui/list.h
index 965a46bfc6..57ca912800 100644
--- a/apps/gui/list.h
+++ b/apps/gui/list.h
@@ -94,7 +94,10 @@ struct gui_synclist
94 /* wether the text of the whole items of the list have to be 94 /* wether the text of the whole items of the list have to be
95 * scrolled or only for the selected item */ 95 * scrolled or only for the selected item */
96 bool scroll_all; 96 bool scroll_all;
97 97 /*
98 * if true the selection bar will not be drawn
99 */
100 bool hide_selection;
98 int nb_items; 101 int nb_items;
99 int selected_item; 102 int selected_item;
100 int start_item[NB_SCREENS]; /* the item that is displayed at the top of the screen */ 103 int start_item[NB_SCREENS]; /* the item that is displayed at the top of the screen */