diff options
author | Jaakko Keränen <jaakko.keranen@iki.fi> | 2021-04-22 10:48:20 +0300 |
---|---|---|
committer | Jaakko Keränen <jaakko.keranen@iki.fi> | 2021-04-22 10:48:20 +0300 |
commit | c56870ab69b71887d703f51881c26ac79f4b7969 (patch) | |
tree | 9c8e70f49b15265d773c55f29056808b40963ee3 /src/ui/util.c | |
parent | 4b7c4ef2659d75ece4d63100a55c278f7c810c9e (diff) |
SmoothScroll is a UI utility; moved it
Diffstat (limited to 'src/ui/util.c')
-rw-r--r-- | src/ui/util.c | 103 |
1 files changed, 103 insertions, 0 deletions
diff --git a/src/ui/util.c b/src/ui/util.c index 877ec7c1..8d1430f8 100644 --- a/src/ui/util.c +++ b/src/ui/util.c | |||
@@ -36,6 +36,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ | |||
36 | #include "keys.h" | 36 | #include "keys.h" |
37 | #include "widget.h" | 37 | #include "widget.h" |
38 | #include "text.h" | 38 | #include "text.h" |
39 | #include "touch.h" | ||
39 | #include "window.h" | 40 | #include "window.h" |
40 | 41 | ||
41 | #if defined (iPlatformAppleMobile) | 42 | #if defined (iPlatformAppleMobile) |
@@ -444,6 +445,108 @@ iInt2 delta_Click(const iClick *d) { | |||
444 | return sub_I2(d->pos, d->startPos); | 445 | return sub_I2(d->pos, d->startPos); |
445 | } | 446 | } |
446 | 447 | ||
448 | /*----------------------------------------------------------------------------------------------*/ | ||
449 | |||
450 | void init_SmoothScroll(iSmoothScroll *d, iWidget *owner, iSmoothScrollNotifyFunc notify) { | ||
451 | reset_SmoothScroll(d); | ||
452 | d->widget = owner; | ||
453 | d->notify = notify; | ||
454 | } | ||
455 | |||
456 | void reset_SmoothScroll(iSmoothScroll *d) { | ||
457 | init_Anim(&d->pos, 0); | ||
458 | d->max = 0; | ||
459 | d->overscroll = (deviceType_App() != desktop_AppDeviceType ? 100 * gap_UI : 0); | ||
460 | } | ||
461 | |||
462 | void setMax_SmoothScroll(iSmoothScroll *d, int max) { | ||
463 | max = iMax(0, max); | ||
464 | if (max != d->max) { | ||
465 | d->max = max; | ||
466 | if (targetValue_Anim(&d->pos) > d->max) { | ||
467 | d->pos.to = d->max; | ||
468 | } | ||
469 | } | ||
470 | } | ||
471 | |||
472 | static int overscroll_SmoothScroll_(const iSmoothScroll *d) { | ||
473 | if (d->overscroll) { | ||
474 | const int y = value_Anim(&d->pos); | ||
475 | if (y <= 0) { | ||
476 | return y; | ||
477 | } | ||
478 | if (y >= d->max) { | ||
479 | return y - d->max; | ||
480 | } | ||
481 | } | ||
482 | return 0; | ||
483 | } | ||
484 | |||
485 | float pos_SmoothScroll(const iSmoothScroll *d) { | ||
486 | return value_Anim(&d->pos) - overscroll_SmoothScroll_(d) * 0.667f; | ||
487 | } | ||
488 | |||
489 | iBool isFinished_SmoothScroll(const iSmoothScroll *d) { | ||
490 | return isFinished_Anim(&d->pos); | ||
491 | } | ||
492 | |||
493 | void moveSpan_SmoothScroll(iSmoothScroll *d, int offset, uint32_t span) { | ||
494 | #if !defined (iPlatformMobile) | ||
495 | if (!prefs_App()->smoothScrolling) { | ||
496 | span = 0; /* always instant */ | ||
497 | } | ||
498 | #endif | ||
499 | int destY = targetValue_Anim(&d->pos) + offset; | ||
500 | if (destY < -d->overscroll) { | ||
501 | destY = -d->overscroll; | ||
502 | } | ||
503 | if (d->max > 0) { | ||
504 | if (destY >= d->max + d->overscroll) { | ||
505 | destY = d->max + d->overscroll; | ||
506 | } | ||
507 | } | ||
508 | else { | ||
509 | destY = 0; | ||
510 | } | ||
511 | if (span) { | ||
512 | setValueEased_Anim(&d->pos, destY, span); | ||
513 | } | ||
514 | else { | ||
515 | setValue_Anim(&d->pos, destY, 0); | ||
516 | } | ||
517 | if (d->overscroll && widgetMode_Touch(d->widget) == momentum_WidgetTouchMode) { | ||
518 | const int osDelta = overscroll_SmoothScroll_(d); | ||
519 | if (osDelta) { | ||
520 | const float remaining = stopWidgetMomentum_Touch(d->widget); | ||
521 | span = iMini(1000, 50 * sqrt(remaining / gap_UI)); | ||
522 | setValue_Anim(&d->pos, osDelta < 0 ? 0 : d->max, span); | ||
523 | d->pos.flags = bounce_AnimFlag | easeOut_AnimFlag | softer_AnimFlag; | ||
524 | // printf("remaining: %f dur: %d\n", remaining, duration); | ||
525 | d->pos.bounce = (osDelta < 0 ? -1 : 1) * | ||
526 | iMini(5 * d->overscroll, remaining * remaining * 0.00005f); | ||
527 | } | ||
528 | } | ||
529 | if (d->notify) { | ||
530 | d->notify(d->widget, offset, span); | ||
531 | } | ||
532 | } | ||
533 | |||
534 | void move_SmoothScroll(iSmoothScroll *d, int offset) { | ||
535 | moveSpan_SmoothScroll(d, offset, 0 /* instantly */); | ||
536 | } | ||
537 | |||
538 | iBool processEvent_SmoothScroll(iSmoothScroll *d, const SDL_Event *ev) { | ||
539 | if (ev->type == SDL_USEREVENT && ev->user.code == widgetTouchEnds_UserEventCode) { | ||
540 | const int osDelta = overscroll_SmoothScroll_(d); | ||
541 | if (osDelta) { | ||
542 | moveSpan_SmoothScroll(d, -osDelta, 100 * sqrt(iAbs(osDelta) / gap_UI)); | ||
543 | d->pos.flags = easeOut_AnimFlag | muchSofter_AnimFlag; | ||
544 | } | ||
545 | return iTrue; | ||
546 | } | ||
547 | return iFalse; | ||
548 | } | ||
549 | |||
447 | /*-----------------------------------------------------------------------------------------------*/ | 550 | /*-----------------------------------------------------------------------------------------------*/ |
448 | 551 | ||
449 | iWidget *makePadding_Widget(int size) { | 552 | iWidget *makePadding_Widget(int size) { |