diff options
author | Jaakko Keränen <jaakko.keranen@iki.fi> | 2021-11-24 08:29:08 +0200 |
---|---|---|
committer | Jaakko Keränen <jaakko.keranen@iki.fi> | 2021-11-24 08:29:08 +0200 |
commit | 83b560ddd19703d52c6a2cfe9ad6da7f9f0c9eb8 (patch) | |
tree | 34bb2869fdca6d34bfa0c968cc0ff5f2c83f63a6 /src/ui | |
parent | 343c8fcf70e6eb3346e77248719a0ce8f3104624 (diff) |
DocumentWidget: Improved footer buttons positioning
No more animation offset hacks: just reposition the buttons whenever the view is scrolling.
Fixed glitches with document centering. The page margins are a bit complicated as they change depending on whether the banner is visible.
Diffstat (limited to 'src/ui')
-rw-r--r-- | src/ui/documentwidget.c | 74 |
1 files changed, 43 insertions, 31 deletions
diff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c index 0f0aeae8..b70f48e4 100644 --- a/src/ui/documentwidget.c +++ b/src/ui/documentwidget.c | |||
@@ -523,10 +523,23 @@ static int documentTopPad_DocumentWidget_(const iDocumentWidget *d) { | |||
523 | return isEmpty_Banner(d->banner) ? 0 : lineHeight_Text(paragraph_FontId); | 523 | return isEmpty_Banner(d->banner) ? 0 : lineHeight_Text(paragraph_FontId); |
524 | } | 524 | } |
525 | 525 | ||
526 | static int documentTopMargin_DocumentWidget_(const iDocumentWidget *d) { | ||
527 | return (isEmpty_Banner(d->banner) ? d->pageMargin * gap_UI : height_Banner(d->banner)) + | ||
528 | documentTopPad_DocumentWidget_(d); | ||
529 | } | ||
530 | |||
526 | static int pageHeight_DocumentWidget_(const iDocumentWidget *d) { | 531 | static int pageHeight_DocumentWidget_(const iDocumentWidget *d) { |
527 | return height_Banner(d->banner) + documentTopPad_DocumentWidget_(d) + size_GmDocument(d->doc).y; | 532 | return height_Banner(d->banner) + documentTopPad_DocumentWidget_(d) + size_GmDocument(d->doc).y; |
528 | } | 533 | } |
529 | 534 | ||
535 | static int footerButtonsHeight_DocumentWidget_(const iDocumentWidget *d) { | ||
536 | int height = height_Widget(d->footerButtons); | ||
537 | // if (height) { | ||
538 | // height += 3 * gap_UI; /* padding */ | ||
539 | // } | ||
540 | return height; | ||
541 | } | ||
542 | |||
530 | static iRect documentBounds_DocumentWidget_(const iDocumentWidget *d) { | 543 | static iRect documentBounds_DocumentWidget_(const iDocumentWidget *d) { |
531 | const iRect bounds = bounds_Widget(constAs_Widget(d)); | 544 | const iRect bounds = bounds_Widget(constAs_Widget(d)); |
532 | const int margin = gap_UI * d->pageMargin; | 545 | const int margin = gap_UI * d->pageMargin; |
@@ -537,29 +550,34 @@ static iRect documentBounds_DocumentWidget_(const iDocumentWidget *d) { | |||
537 | rect.size.y = height_Rect(bounds) - margin; | 550 | rect.size.y = height_Rect(bounds) - margin; |
538 | iBool wasCentered = iFalse; | 551 | iBool wasCentered = iFalse; |
539 | if (d->flags & centerVertically_DocumentWidgetFlag) { | 552 | if (d->flags & centerVertically_DocumentWidgetFlag) { |
540 | const iInt2 docSize = addY_I2(size_GmDocument(d->doc), | 553 | const int docSize = size_GmDocument(d->doc).y + |
541 | iMax(height_Widget(d->footerButtons), height_Widget(d->phoneToolbar))); | 554 | documentTopMargin_DocumentWidget_(d); |
542 | if (size_GmDocument(d->doc).y == 0) { | 555 | if (size_GmDocument(d->doc).y == 0) { |
556 | /* Document is empty; maybe just showing an error banner. */ | ||
543 | rect.pos.y = top_Rect(bounds) + height_Rect(bounds) / 2 - | 557 | rect.pos.y = top_Rect(bounds) + height_Rect(bounds) / 2 - |
544 | documentTopPad_DocumentWidget_(d) - height_Banner(d->banner) / 2; | 558 | documentTopPad_DocumentWidget_(d) - height_Banner(d->banner) / 2; |
545 | rect.size.y = 0; | 559 | rect.size.y = 0; |
546 | wasCentered = iTrue; | 560 | wasCentered = iTrue; |
547 | } | 561 | } |
548 | else if (docSize.y < rect.size.y) { | 562 | else if (docSize < rect.size.y - footerButtonsHeight_DocumentWidget_(d)) { |
549 | /* Center vertically if page is short. */ | 563 | /* TODO: Phone toolbar? */ |
550 | int offset = iMax(0, height_Rect(bounds) / 2 | 564 | /* Center vertically when the document is short. */ |
551 | - documentTopPad_DocumentWidget_(d) | 565 | const int relMidY = (height_Rect(bounds) - footerButtonsHeight_DocumentWidget_(d)) / 2; |
552 | - height_Banner(d->banner) | 566 | const int visHeight = size_GmDocument(d->doc).y; |
553 | - size_GmDocument(d->doc).y / 2); | 567 | const int offset = -height_Banner(d->banner) - documentTopPad_DocumentWidget_(d); |
554 | rect.pos.y = top_Rect(bounds) + offset; | 568 | rect.pos.y = top_Rect(bounds) + iMaxi(0, relMidY - visHeight / 2 + offset); |
555 | rect.size.y = docSize.y; | 569 | rect.size.y = size_GmDocument(d->doc).y + documentTopMargin_DocumentWidget_(d); |
556 | wasCentered = iTrue; | 570 | wasCentered = iTrue; |
557 | } | 571 | } |
558 | } | 572 | } |
559 | if (!wasCentered && !isEmpty_Banner(d->banner)) { | 573 | if (!wasCentered) { |
560 | /* The banner overtakes the top banner. */ | 574 | /* The banner overtakes the top margin. */ |
561 | rect.pos.y -= margin; | 575 | if (!isEmpty_Banner(d->banner)) { |
562 | rect.size.y -= margin; | 576 | rect.pos.y -= margin; |
577 | } | ||
578 | else { | ||
579 | rect.size.y -= margin; | ||
580 | } | ||
563 | } | 581 | } |
564 | return rect; | 582 | return rect; |
565 | } | 583 | } |
@@ -895,29 +913,22 @@ static void updateVisible_DocumentWidget_(iDocumentWidget *d) { | |||
895 | /* Reposition the footer buttons as appropriate. */ | 913 | /* Reposition the footer buttons as appropriate. */ |
896 | /* TODO: You can just position `footerButtons` here completely without having to get | 914 | /* TODO: You can just position `footerButtons` here completely without having to get |
897 | `Widget` involved with the offset in any way. */ | 915 | `Widget` involved with the offset in any way. */ |
898 | if (d->footerButtons) { | ||
899 | const iRect bounds = bounds_Widget(as_Widget(d)); | ||
900 | const iRect docBounds = documentBounds_DocumentWidget_(d); | ||
901 | const int hPad = (width_Rect(bounds) - iMin(120 * gap_UI, width_Rect(docBounds))) / 2; | ||
902 | const int vPad = 3 * gap_UI; | ||
903 | setPadding_Widget(d->footerButtons, hPad, vPad, hPad, vPad); | ||
904 | d->footerButtons->animOffsetRef = (scrollMax > 0 ? &d->scrollY.pos : NULL); | ||
905 | if (scrollMax <= 0) { | ||
906 | d->footerButtons->animOffsetRef = NULL; | ||
907 | d->footerButtons->rect.pos.y = height_Rect(bounds) - height_Widget(d->footerButtons); | ||
908 | } | ||
909 | else { | ||
910 | d->footerButtons->animOffsetRef = &d->scrollY.pos; | ||
911 | d->footerButtons->rect.pos.y = pageHeight_DocumentWidget_(d) + 2 * gap_UI * d->pageMargin; | ||
912 | // + height_Widget(d->phoneToolbar); | ||
913 | } | ||
914 | } | ||
915 | setRange_ScrollWidget(d->scroll, (iRangei){ 0, scrollMax }); | 916 | setRange_ScrollWidget(d->scroll, (iRangei){ 0, scrollMax }); |
916 | const int docSize = pageHeight_DocumentWidget_(d) + iMax(height_Widget(d->phoneToolbar), | 917 | const int docSize = pageHeight_DocumentWidget_(d) + iMax(height_Widget(d->phoneToolbar), |
917 | height_Widget(d->footerButtons)); | 918 | height_Widget(d->footerButtons)); |
919 | const float scrollPos = pos_SmoothScroll(&d->scrollY); | ||
918 | setThumb_ScrollWidget(d->scroll, | 920 | setThumb_ScrollWidget(d->scroll, |
919 | pos_SmoothScroll(&d->scrollY), | 921 | pos_SmoothScroll(&d->scrollY), |
920 | docSize > 0 ? height_Rect(bounds) * size_Range(&visRange) / docSize : 0); | 922 | docSize > 0 ? height_Rect(bounds) * size_Range(&visRange) / docSize : 0); |
923 | if (d->footerButtons) { | ||
924 | const iRect bounds = bounds_Widget(as_Widget(d)); | ||
925 | const iRect docBounds = documentBounds_DocumentWidget_(d); | ||
926 | const int hPad = (width_Rect(bounds) - iMin(120 * gap_UI, width_Rect(docBounds))) / 2; | ||
927 | const int vPad = 3 * gap_UI; | ||
928 | setPadding_Widget(d->footerButtons, hPad, 0, hPad, vPad); | ||
929 | d->footerButtons->rect.pos.y = height_Rect(bounds) - height_Widget(d->footerButtons) + | ||
930 | (scrollMax > 0 ? scrollMax - scrollPos : 0); | ||
931 | } | ||
921 | clear_PtrArray(&d->visibleLinks); | 932 | clear_PtrArray(&d->visibleLinks); |
922 | clear_PtrArray(&d->visibleWideRuns); | 933 | clear_PtrArray(&d->visibleWideRuns); |
923 | clear_PtrArray(&d->visiblePre); | 934 | clear_PtrArray(&d->visiblePre); |
@@ -5176,6 +5187,7 @@ static void draw_DocumentWidget_(const iDocumentWidget *d) { | |||
5176 | mut->flags &= ~refChildrenOffset_WidgetFlag; | 5187 | mut->flags &= ~refChildrenOffset_WidgetFlag; |
5177 | } | 5188 | } |
5178 | } | 5189 | } |
5190 | // drawRect_Paint(&ctx.paint, docBounds, red_ColorId); | ||
5179 | } | 5191 | } |
5180 | 5192 | ||
5181 | /*----------------------------------------------------------------------------------------------*/ | 5193 | /*----------------------------------------------------------------------------------------------*/ |