diff options
Diffstat (limited to 'apps/gui/bitmap')
-rw-r--r-- | apps/gui/bitmap/list.c | 181 |
1 files changed, 123 insertions, 58 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. */ |
311 | static bool scrolling=false; | 314 | static 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 | |||
320 | static 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 | */ | ||
326 | static int last_position=0; | ||
327 | |||
312 | 328 | ||
313 | static int gui_synclist_touchscreen_scrollbar(struct gui_synclist * gui_list, | 329 | static 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 | **/ | ||
362 | static 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 | |||
345 | unsigned gui_synclist_do_touchscreen(struct gui_synclist * gui_list) | 382 | unsigned 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; |