summaryrefslogtreecommitdiff
path: root/src/ui
diff options
context:
space:
mode:
authorJaakko Keränen <jaakko.keranen@iki.fi>2021-04-22 10:48:20 +0300
committerJaakko Keränen <jaakko.keranen@iki.fi>2021-04-22 10:48:20 +0300
commitc56870ab69b71887d703f51881c26ac79f4b7969 (patch)
tree9c8e70f49b15265d773c55f29056808b40963ee3 /src/ui
parent4b7c4ef2659d75ece4d63100a55c278f7c810c9e (diff)
SmoothScroll is a UI utility; moved it
Diffstat (limited to 'src/ui')
-rw-r--r--src/ui/documentwidget.c117
-rw-r--r--src/ui/util.c103
-rw-r--r--src/ui/util.h25
3 files changed, 128 insertions, 117 deletions
diff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c
index 635bf3e6..1298dda9 100644
--- a/src/ui/documentwidget.c
+++ b/src/ui/documentwidget.c
@@ -198,123 +198,6 @@ static void prerender_DocumentWidget_ (iAny *);
198static void scrollBegan_DocumentWidget_ (iAnyObject *, int, uint32_t); 198static void scrollBegan_DocumentWidget_ (iAnyObject *, int, uint32_t);
199 199
200static const int smoothDuration_DocumentWidget_ = 600; /* milliseconds */ 200static const int smoothDuration_DocumentWidget_ = 600; /* milliseconds */
201static const int outlineMinWidth_DocumentWdiget_ = 45; /* times gap_UI */
202static const int outlineMaxWidth_DocumentWidget_ = 65; /* times gap_UI */
203static const int outlinePadding_DocumentWidget_ = 3; /* times gap_UI */
204
205
206iDeclareType(SmoothScroll)
207
208typedef void (*iSmoothScrollNotifyFunc)(iAnyObject *, int offset, uint32_t span);
209
210struct Impl_SmoothScroll {
211 iWidget *widget;
212 iSmoothScrollNotifyFunc notify;
213 iAnim pos;
214 int max;
215 int overscroll;
216};
217
218void reset_SmoothScroll(iSmoothScroll *d) {
219 init_Anim(&d->pos, 0);
220 d->max = 0;
221 d->overscroll = (deviceType_App() != desktop_AppDeviceType ? 100 * gap_UI : 0);
222}
223
224void init_SmoothScroll(iSmoothScroll *d, iWidget *owner, iSmoothScrollNotifyFunc notify) {
225 d->widget = owner;
226 d->notify = notify;
227 reset_SmoothScroll(d);
228}
229
230void setMax_SmoothScroll(iSmoothScroll *d, int max) {
231 max = iMax(0, max);
232 if (max != d->max) {
233 d->max = max;
234 if (targetValue_Anim(&d->pos) > d->max) {
235 d->pos.to = d->max;
236 }
237 }
238}
239
240static int overscroll_SmoothScroll_(const iSmoothScroll *d) {
241 if (d->overscroll) {
242 const int y = value_Anim(&d->pos);
243 if (y <= 0) {
244 return y;
245 }
246 if (y >= d->max) {
247 return y - d->max;
248 }
249 }
250 return 0;
251}
252
253float pos_SmoothScroll(const iSmoothScroll *d) {
254 return value_Anim(&d->pos) - overscroll_SmoothScroll_(d) * 0.667f;
255}
256
257iBool isFinished_SmoothScroll(const iSmoothScroll *d) {
258 return isFinished_Anim(&d->pos);
259}
260
261void moveSpan_SmoothScroll(iSmoothScroll *d, int offset, uint32_t span) {
262#if !defined (iPlatformMobile)
263 if (!prefs_App()->smoothScrolling) {
264 span = 0; /* always instant */
265 }
266#endif
267 int destY = targetValue_Anim(&d->pos) + offset;
268 if (destY < -d->overscroll) {
269 destY = -d->overscroll;
270 }
271 if (d->max > 0) {
272 if (destY >= d->max + d->overscroll) {
273 destY = d->max + d->overscroll;
274 }
275 }
276 else {
277 destY = 0;
278 }
279 if (span) {
280 setValueEased_Anim(&d->pos, destY, span);
281 }
282 else {
283 setValue_Anim(&d->pos, destY, 0);
284 }
285 if (d->overscroll && widgetMode_Touch(d->widget) == momentum_WidgetTouchMode) {
286 const int osDelta = overscroll_SmoothScroll_(d);
287 if (osDelta) {
288 const float remaining = stopWidgetMomentum_Touch(d->widget);
289 span = iMini(1000, 50 * sqrt(remaining / gap_UI));
290 setValue_Anim(&d->pos, osDelta < 0 ? 0 : d->max, span);
291 d->pos.flags = bounce_AnimFlag | easeOut_AnimFlag | softer_AnimFlag;
292// printf("remaining: %f dur: %d\n", remaining, duration);
293 d->pos.bounce = (osDelta < 0 ? -1 : 1) *
294 iMini(5 * d->overscroll, remaining * remaining * 0.00005f);
295 }
296 }
297 if (d->notify) {
298 d->notify(d->widget, offset, span);
299 }
300}
301
302void move_SmoothScroll(iSmoothScroll *d, int offset) {
303 moveSpan_SmoothScroll(d, offset, 0 /* instantly */);
304}
305
306iBool processEvent_SmoothScroll(iSmoothScroll *d, const SDL_Event *ev) {
307 if (ev->type == SDL_USEREVENT && ev->user.code == widgetTouchEnds_UserEventCode) {
308 const int osDelta = overscroll_SmoothScroll_(d);
309 if (osDelta) {
310 moveSpan_SmoothScroll(d, -osDelta, 100 * sqrt(iAbs(osDelta) / gap_UI));
311 d->pos.flags = easeOut_AnimFlag | muchSofter_AnimFlag;
312 }
313 return iTrue;
314 }
315 return iFalse;
316}
317
318 201
319enum iRequestState { 202enum iRequestState {
320 blank_RequestState, 203 blank_RequestState,
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
450void init_SmoothScroll(iSmoothScroll *d, iWidget *owner, iSmoothScrollNotifyFunc notify) {
451 reset_SmoothScroll(d);
452 d->widget = owner;
453 d->notify = notify;
454}
455
456void 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
462void 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
472static 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
485float pos_SmoothScroll(const iSmoothScroll *d) {
486 return value_Anim(&d->pos) - overscroll_SmoothScroll_(d) * 0.667f;
487}
488
489iBool isFinished_SmoothScroll(const iSmoothScroll *d) {
490 return isFinished_Anim(&d->pos);
491}
492
493void 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
534void move_SmoothScroll(iSmoothScroll *d, int offset) {
535 moveSpan_SmoothScroll(d, offset, 0 /* instantly */);
536}
537
538iBool 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
449iWidget *makePadding_Widget(int size) { 552iWidget *makePadding_Widget(int size) {
diff --git a/src/ui/util.h b/src/ui/util.h
index 191b8a87..223982a8 100644
--- a/src/ui/util.h
+++ b/src/ui/util.h
@@ -163,6 +163,31 @@ iInt2 delta_Click (const iClick *);
163 163
164/*-----------------------------------------------------------------------------------------------*/ 164/*-----------------------------------------------------------------------------------------------*/
165 165
166iDeclareType(SmoothScroll)
167
168typedef void (*iSmoothScrollNotifyFunc)(iAnyObject *, int offset, uint32_t span);
169
170struct Impl_SmoothScroll {
171 iAnim pos;
172 int max;
173 int overscroll;
174 iWidget *widget;
175 iSmoothScrollNotifyFunc notify;
176};
177
178void init_SmoothScroll (iSmoothScroll *, iWidget *owner, iSmoothScrollNotifyFunc notify);
179
180void reset_SmoothScroll (iSmoothScroll *);
181void setMax_SmoothScroll (iSmoothScroll *, int max);
182void move_SmoothScroll (iSmoothScroll *, int offset);
183void moveSpan_SmoothScroll (iSmoothScroll *, int offset, uint32_t span);
184iBool processEvent_SmoothScroll (iSmoothScroll *, const SDL_Event *ev);
185
186float pos_SmoothScroll (const iSmoothScroll *);
187iBool isFinished_SmoothScroll (const iSmoothScroll *);
188
189/*-----------------------------------------------------------------------------------------------*/
190
166iWidget * makePadding_Widget (int size); 191iWidget * makePadding_Widget (int size);
167iLabelWidget * makeHeading_Widget (const char *text); 192iLabelWidget * makeHeading_Widget (const char *text);
168iWidget * makeHDiv_Widget (void); 193iWidget * makeHDiv_Widget (void);