diff options
Diffstat (limited to 'src/ui/documentwidget.c')
-rw-r--r-- | src/ui/documentwidget.c | 295 |
1 files changed, 148 insertions, 147 deletions
diff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c index 963bae8f..17111ed0 100644 --- a/src/ui/documentwidget.c +++ b/src/ui/documentwidget.c | |||
@@ -27,6 +27,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ | |||
27 | 27 | ||
28 | #include "app.h" | 28 | #include "app.h" |
29 | #include "audio/player.h" | 29 | #include "audio/player.h" |
30 | #include "banner.h" | ||
30 | #include "bookmarks.h" | 31 | #include "bookmarks.h" |
31 | #include "command.h" | 32 | #include "command.h" |
32 | #include "defs.h" | 33 | #include "defs.h" |
@@ -280,6 +281,7 @@ struct Impl_DocumentWidget { | |||
280 | iTime sourceTime; | 281 | iTime sourceTime; |
281 | iGempub * sourceGempub; /* NULL unless the page is Gempub content */ | 282 | iGempub * sourceGempub; /* NULL unless the page is Gempub content */ |
282 | iGmDocument * doc; | 283 | iGmDocument * doc; |
284 | iBanner * banner; | ||
283 | 285 | ||
284 | /* Rendering: */ | 286 | /* Rendering: */ |
285 | int pageMargin; | 287 | int pageMargin; |
@@ -339,6 +341,7 @@ void init_DocumentWidget(iDocumentWidget *d) { | |||
339 | d->isRequestUpdated = iFalse; | 341 | d->isRequestUpdated = iFalse; |
340 | d->media = new_ObjectList(); | 342 | d->media = new_ObjectList(); |
341 | d->doc = new_GmDocument(); | 343 | d->doc = new_GmDocument(); |
344 | d->banner = new_Banner(); | ||
342 | d->redirectCount = 0; | 345 | d->redirectCount = 0; |
343 | d->ordinalBase = 0; | 346 | d->ordinalBase = 0; |
344 | d->initNormScrollY = 0; | 347 | d->initNormScrollY = 0; |
@@ -429,6 +432,7 @@ void deinit_DocumentWidget(iDocumentWidget *d) { | |||
429 | deinit_Block(&d->sourceContent); | 432 | deinit_Block(&d->sourceContent); |
430 | deinit_String(&d->sourceMime); | 433 | deinit_String(&d->sourceMime); |
431 | deinit_String(&d->sourceHeader); | 434 | deinit_String(&d->sourceHeader); |
435 | delete_Banner(d->banner); | ||
432 | iRelease(d->doc); | 436 | iRelease(d->doc); |
433 | if (d->mediaTimer) { | 437 | if (d->mediaTimer) { |
434 | SDL_RemoveTimer(d->mediaTimer); | 438 | SDL_RemoveTimer(d->mediaTimer); |
@@ -512,35 +516,67 @@ static int documentWidth_DocumentWidget_(const iDocumentWidget *d) { | |||
512 | prefs->lineWidth * prefs->zoomPercent / 100); | 516 | prefs->lineWidth * prefs->zoomPercent / 100); |
513 | } | 517 | } |
514 | 518 | ||
519 | static int documentTopPad_DocumentWidget_(const iDocumentWidget *d) { | ||
520 | /* Amount of space between banner and top of the document. */ | ||
521 | return isEmpty_Banner(d->banner) ? 0 : lineHeight_Text(paragraph_FontId); | ||
522 | } | ||
523 | |||
524 | static int pageHeight_DocumentWidget_(const iDocumentWidget *d) { | ||
525 | return height_Banner(d->banner) + documentTopPad_DocumentWidget_(d) + size_GmDocument(d->doc).y; | ||
526 | } | ||
527 | |||
515 | static iRect documentBounds_DocumentWidget_(const iDocumentWidget *d) { | 528 | static iRect documentBounds_DocumentWidget_(const iDocumentWidget *d) { |
516 | const iRect bounds = bounds_Widget(constAs_Widget(d)); | 529 | const iRect bounds = bounds_Widget(constAs_Widget(d)); |
517 | const int margin = gap_UI * d->pageMargin; | 530 | const int margin = gap_UI * d->pageMargin; |
518 | iRect rect; | 531 | iRect rect; |
519 | rect.size.x = documentWidth_DocumentWidget_(d); | 532 | rect.size.x = documentWidth_DocumentWidget_(d); |
520 | rect.pos.x = mid_Rect(bounds).x - rect.size.x / 2; | 533 | rect.pos.x = mid_Rect(bounds).x - rect.size.x / 2; |
521 | rect.pos.y = top_Rect(bounds); | 534 | rect.pos.y = top_Rect(bounds) + margin; |
522 | rect.size.y = height_Rect(bounds) - margin; | 535 | rect.size.y = height_Rect(bounds) - margin; |
523 | const iGmRun *banner = siteBanner_GmDocument(d->doc); | 536 | iBool wasCentered = iFalse; |
524 | if (!banner) { | ||
525 | rect.pos.y += margin; | ||
526 | rect.size.y -= margin; | ||
527 | } | ||
528 | if (d->flags & centerVertically_DocumentWidgetFlag) { | 537 | if (d->flags & centerVertically_DocumentWidgetFlag) { |
529 | const iInt2 docSize = addY_I2(size_GmDocument(d->doc), | 538 | const iInt2 docSize = addY_I2(size_GmDocument(d->doc), |
530 | iMax(height_Widget(d->footerButtons), height_Widget(d->phoneToolbar))); | 539 | iMax(height_Widget(d->footerButtons), height_Widget(d->phoneToolbar))); |
531 | if (docSize.y < rect.size.y) { | 540 | if (docSize.y < rect.size.y) { |
532 | /* Center vertically if short. There is one empty paragraph line's worth of margin | 541 | /* Center vertically if short. There is one empty paragraph line's worth of margin |
533 | between the banner and the page contents. */ | 542 | between the banner and the page contents. */ |
534 | const int bannerHeight = banner ? height_Rect(banner->visBounds) : 0; | 543 | // const int bannerHeight = 0; //banner ? height_Rect(banner->visBounds) : 0; |
535 | int offset = iMax(0, (rect.size.y + margin - docSize.y - bannerHeight - | 544 | #if 0 |
536 | lineHeight_Text(paragraph_FontId)) / 2); | 545 | int offset = iMax(0, (rect.size.y + margin - size_GmDocument(d->doc).y |
537 | rect.pos.y += offset; | 546 | //- lineHeight_Text(paragraph_FontId) |
547 | ) / 2 - height_Banner(d->banner) | ||
548 | //- | ||
549 | //documentTopPad_DocumentWidget_(d) | ||
550 | ); | ||
551 | #endif | ||
552 | int offset = iMax(0, height_Rect(bounds) / 2 | ||
553 | // - (isEmpty_Banner(d->banner) ? lineHeight_Text(paragraph_FontId) / 2 : 0) | ||
554 | - documentTopPad_DocumentWidget_(d) | ||
555 | // + lineHeight_Text(paragraph_FontId) / 2 | ||
556 | // - isEmpty_Banner(d->banner) ? | ||
557 | - height_Banner(d->banner) | ||
558 | - size_GmDocument(d->doc).y / 2 | ||
559 | ); | ||
560 | //(//documentTopPad_DocumentWidget_(d) + | ||
561 | //size_GmDocument(d->doc).y) / 2); | ||
562 | rect.pos.y = top_Rect(bounds) + offset; | ||
538 | rect.size.y = docSize.y; | 563 | rect.size.y = docSize.y; |
564 | wasCentered = iTrue; | ||
539 | } | 565 | } |
540 | } | 566 | } |
567 | if (!wasCentered && !isEmpty_Banner(d->banner)) { | ||
568 | /* The banner overtakes the top banner. */ | ||
569 | rect.pos.y -= margin; | ||
570 | rect.size.y -= margin; | ||
571 | } | ||
541 | return rect; | 572 | return rect; |
542 | } | 573 | } |
543 | 574 | ||
575 | static int viewPos_DocumentWidget_(const iDocumentWidget *d) { | ||
576 | return height_Banner(d->banner) + documentTopPad_DocumentWidget_(d) - pos_SmoothScroll(&d->scrollY); | ||
577 | } | ||
578 | |||
579 | #if 0 | ||
544 | static iRect siteBannerRect_DocumentWidget_(const iDocumentWidget *d) { | 580 | static iRect siteBannerRect_DocumentWidget_(const iDocumentWidget *d) { |
545 | const iGmRun *banner = siteBanner_GmDocument(d->doc); | 581 | const iGmRun *banner = siteBanner_GmDocument(d->doc); |
546 | if (!banner) { | 582 | if (!banner) { |
@@ -550,17 +586,23 @@ static iRect siteBannerRect_DocumentWidget_(const iDocumentWidget *d) { | |||
550 | const iInt2 origin = addY_I2(topLeft_Rect(docBounds), -pos_SmoothScroll(&d->scrollY)); | 586 | const iInt2 origin = addY_I2(topLeft_Rect(docBounds), -pos_SmoothScroll(&d->scrollY)); |
551 | return moved_Rect(banner->visBounds, origin); | 587 | return moved_Rect(banner->visBounds, origin); |
552 | } | 588 | } |
589 | #endif | ||
553 | 590 | ||
554 | static iInt2 documentPos_DocumentWidget_(const iDocumentWidget *d, iInt2 pos) { | 591 | static iInt2 documentPos_DocumentWidget_(const iDocumentWidget *d, iInt2 pos) { |
555 | return addY_I2(sub_I2(pos, topLeft_Rect(documentBounds_DocumentWidget_(d))), | 592 | return addY_I2(sub_I2(pos, topLeft_Rect(documentBounds_DocumentWidget_(d))), |
556 | pos_SmoothScroll(&d->scrollY)); | 593 | -viewPos_DocumentWidget_(d)); |
557 | } | 594 | } |
558 | 595 | ||
559 | static iRangei visibleRange_DocumentWidget_(const iDocumentWidget *d) { | 596 | static iRangei visibleRange_DocumentWidget_(const iDocumentWidget *d) { |
560 | const int margin = !hasSiteBanner_GmDocument(d->doc) ? gap_UI * d->pageMargin : 0; | 597 | // const int margin = -documentTopPad_DocumentWidget_(d) + |
561 | return (iRangei){ pos_SmoothScroll(&d->scrollY) - margin, | 598 | // d->pageMargin * gap_UI; |
562 | pos_SmoothScroll(&d->scrollY) + height_Rect(bounds_Widget(constAs_Widget(d))) - | 599 | //const int top = -viewPos_DocumentWidget_(d) - margin; |
563 | margin }; | 600 | int top = pos_SmoothScroll(&d->scrollY) - height_Banner(d->banner) - documentTopPad_DocumentWidget_(d); |
601 | if (isEmpty_Banner(d->banner)) { | ||
602 | /* Top padding is not collapsed. */ | ||
603 | top -= d->pageMargin * gap_UI; | ||
604 | } | ||
605 | return (iRangei){ top, top + height_Rect(bounds_Widget(constAs_Widget(d))) }; | ||
564 | } | 606 | } |
565 | 607 | ||
566 | static void addVisible_DocumentWidget_(void *context, const iGmRun *run) { | 608 | static void addVisible_DocumentWidget_(void *context, const iGmRun *run) { |
@@ -598,7 +640,7 @@ static const iGmRun *lastVisibleLink_DocumentWidget_(const iDocumentWidget *d) { | |||
598 | } | 640 | } |
599 | 641 | ||
600 | static float normScrollPos_DocumentWidget_(const iDocumentWidget *d) { | 642 | static float normScrollPos_DocumentWidget_(const iDocumentWidget *d) { |
601 | const int docSize = size_GmDocument(d->doc).y; | 643 | const int docSize = pageHeight_DocumentWidget_(d); // size_GmDocument(d->doc).y; |
602 | if (docSize) { | 644 | if (docSize) { |
603 | return pos_SmoothScroll(&d->scrollY) / (float) docSize; | 645 | return pos_SmoothScroll(&d->scrollY) / (float) docSize; |
604 | } | 646 | } |
@@ -607,15 +649,9 @@ static float normScrollPos_DocumentWidget_(const iDocumentWidget *d) { | |||
607 | 649 | ||
608 | static int scrollMax_DocumentWidget_(const iDocumentWidget *d) { | 650 | static int scrollMax_DocumentWidget_(const iDocumentWidget *d) { |
609 | const iWidget *w = constAs_Widget(d); | 651 | const iWidget *w = constAs_Widget(d); |
610 | int sm = size_GmDocument(d->doc).y - height_Rect(bounds_Widget(w)) + | 652 | int sm = pageHeight_DocumentWidget_(d) - height_Rect(bounds_Widget(w)) + |
611 | (hasSiteBanner_GmDocument(d->doc) ? 1 : 2) * d->pageMargin * gap_UI + | 653 | (isEmpty_Banner(d->banner) ? 2 : 1) * d->pageMargin * gap_UI + /* top and bottom margins */ |
612 | iMax(height_Widget(d->phoneToolbar), height_Widget(d->footerButtons)); | 654 | iMax(height_Widget(d->phoneToolbar), height_Widget(d->footerButtons)); |
613 | // sm += height_Widget(d->phoneToolbar); | ||
614 | // if (d->phoneToolbar) { | ||
615 | // sm += size_Root(w->root).y - | ||
616 | // top_Rect(boundsWithoutVisualOffset_Widget(d->phoneToolbar)); | ||
617 | // sm += height_Widget(d->phoneToolbar); | ||
618 | // } | ||
619 | return sm; | 655 | return sm; |
620 | } | 656 | } |
621 | 657 | ||
@@ -699,7 +735,8 @@ static void updateHover_DocumentWidget_(iDocumentWidget *d, iInt2 mouse) { | |||
699 | const iGmRun * oldHoverLink = d->hoverLink; | 735 | const iGmRun * oldHoverLink = d->hoverLink; |
700 | d->hoverPre = NULL; | 736 | d->hoverPre = NULL; |
701 | d->hoverLink = NULL; | 737 | d->hoverLink = NULL; |
702 | const iInt2 hoverPos = addY_I2(sub_I2(mouse, topLeft_Rect(docBounds)), pos_SmoothScroll(&d->scrollY)); | 738 | const iInt2 hoverPos = addY_I2(sub_I2(mouse, topLeft_Rect(docBounds)), |
739 | -viewPos_DocumentWidget_(d)); | ||
703 | if (isHoverAllowed_DocumentWidget_(d)) { | 740 | if (isHoverAllowed_DocumentWidget_(d)) { |
704 | iConstForEach(PtrArray, i, &d->visibleLinks) { | 741 | iConstForEach(PtrArray, i, &d->visibleLinks) { |
705 | const iGmRun *run = i.ptr; | 742 | const iGmRun *run = i.ptr; |
@@ -757,8 +794,9 @@ static void updateHover_DocumentWidget_(iDocumentWidget *d, iInt2 mouse) { | |||
757 | 794 | ||
758 | static void updateSideOpacity_DocumentWidget_(iDocumentWidget *d, iBool isAnimated) { | 795 | static void updateSideOpacity_DocumentWidget_(iDocumentWidget *d, iBool isAnimated) { |
759 | float opacity = 0.0f; | 796 | float opacity = 0.0f; |
760 | const iGmRun *banner = siteBanner_GmDocument(d->doc); | 797 | // const iGmRun *banner = siteBanner_GmDocument(d->doc); |
761 | if (banner && bottom_Rect(banner->visBounds) < pos_SmoothScroll(&d->scrollY)) { | 798 | if (!isEmpty_Banner(d->banner) && height_Banner(d->banner) < pos_SmoothScroll(&d->scrollY)) { |
799 | // if (banner && bottom_Rect(banner->visBounds) < pos_SmoothScroll(&d->scrollY)) { | ||
762 | opacity = 1.0f; | 800 | opacity = 1.0f; |
763 | } | 801 | } |
764 | setValue_Anim(&d->sideOpacity, opacity, isAnimated ? (opacity < 0.5f ? 100 : 200) : 0); | 802 | setValue_Anim(&d->sideOpacity, opacity, isAnimated ? (opacity < 0.5f ? 100 : 200) : 0); |
@@ -862,6 +900,7 @@ static void updateVisible_DocumentWidget_(iDocumentWidget *d) { | |||
862 | prefs_App()->centerShortDocs || startsWithCase_String(d->mod.url, "about:") || | 900 | prefs_App()->centerShortDocs || startsWithCase_String(d->mod.url, "about:") || |
863 | !isSuccess_GmStatusCode(d->sourceStatus)); | 901 | !isSuccess_GmStatusCode(d->sourceStatus)); |
864 | const iRangei visRange = visibleRange_DocumentWidget_(d); | 902 | const iRangei visRange = visibleRange_DocumentWidget_(d); |
903 | // printf("visRange: %d...%d\n", visRange.start, visRange.end); | ||
865 | const iRect bounds = bounds_Widget(as_Widget(d)); | 904 | const iRect bounds = bounds_Widget(as_Widget(d)); |
866 | const int scrollMax = updateScrollMax_DocumentWidget_(d); | 905 | const int scrollMax = updateScrollMax_DocumentWidget_(d); |
867 | /* Reposition the footer buttons as appropriate. */ | 906 | /* Reposition the footer buttons as appropriate. */ |
@@ -880,13 +919,13 @@ static void updateVisible_DocumentWidget_(iDocumentWidget *d) { | |||
880 | } | 919 | } |
881 | else { | 920 | else { |
882 | d->footerButtons->animOffsetRef = &d->scrollY.pos; | 921 | d->footerButtons->animOffsetRef = &d->scrollY.pos; |
883 | d->footerButtons->rect.pos.y = size_GmDocument(d->doc).y + 2 * gap_UI * d->pageMargin; | 922 | d->footerButtons->rect.pos.y = pageHeight_DocumentWidget_(d) + 2 * gap_UI * d->pageMargin; |
884 | // + height_Widget(d->phoneToolbar); | 923 | // + height_Widget(d->phoneToolbar); |
885 | } | 924 | } |
886 | } | 925 | } |
887 | setRange_ScrollWidget(d->scroll, (iRangei){ 0, scrollMax }); | 926 | setRange_ScrollWidget(d->scroll, (iRangei){ 0, scrollMax }); |
888 | const int docSize = size_GmDocument(d->doc).y + iMax(height_Widget(d->phoneToolbar), | 927 | const int docSize = pageHeight_DocumentWidget_(d) + iMax(height_Widget(d->phoneToolbar), |
889 | height_Widget(d->footerButtons)); | 928 | height_Widget(d->footerButtons)); |
890 | setThumb_ScrollWidget(d->scroll, | 929 | setThumb_ScrollWidget(d->scroll, |
891 | pos_SmoothScroll(&d->scrollY), | 930 | pos_SmoothScroll(&d->scrollY), |
892 | docSize > 0 ? height_Rect(bounds) * size_Range(&visRange) / docSize : 0); | 931 | docSize > 0 ? height_Rect(bounds) * size_Range(&visRange) / docSize : 0); |
@@ -906,6 +945,11 @@ static void updateVisible_DocumentWidget_(iDocumentWidget *d) { | |||
906 | updateHover_DocumentWidget_(d, mouseCoord_Window(get_Window(), 0)); | 945 | updateHover_DocumentWidget_(d, mouseCoord_Window(get_Window(), 0)); |
907 | updateSideOpacity_DocumentWidget_(d, iTrue); | 946 | updateSideOpacity_DocumentWidget_(d, iTrue); |
908 | animateMedia_DocumentWidget_(d); | 947 | animateMedia_DocumentWidget_(d); |
948 | setPos_Banner(d->banner, addY_I2(topLeft_Rect(documentBounds_DocumentWidget_(d)), | ||
949 | -pos_SmoothScroll(&d->scrollY))); | ||
950 | /*init_I2(documentBounds_DocumentWidget_(d).pos.x, | ||
951 | viewPos_DocumentWidget_(d) - | ||
952 | documentTopPad_DocumentWidget_(d)));*/ | ||
909 | /* Remember scroll positions of recently visited pages. */ { | 953 | /* Remember scroll positions of recently visited pages. */ { |
910 | iRecentUrl *recent = mostRecentUrl_History(d->mod.history); | 954 | iRecentUrl *recent = mostRecentUrl_History(d->mod.history); |
911 | if (recent && docSize && d->state == ready_RequestState) { | 955 | if (recent && docSize && d->state == ready_RequestState) { |
@@ -1015,18 +1059,18 @@ static void invalidate_DocumentWidget_(iDocumentWidget *d) { | |||
1015 | clear_PtrSet(d->invalidRuns); | 1059 | clear_PtrSet(d->invalidRuns); |
1016 | } | 1060 | } |
1017 | 1061 | ||
1018 | static iRangecc bannerText_DocumentWidget_(const iDocumentWidget *d) { | 1062 | static iRangecc siteText_DocumentWidget_(const iDocumentWidget *d) { |
1019 | return isEmpty_String(d->titleUser) ? range_String(bannerText_GmDocument(d->doc)) | 1063 | return isEmpty_String(d->titleUser) ? urlHost_String(d->mod.url) |
1020 | : range_String(d->titleUser); | 1064 | : range_String(d->titleUser); |
1021 | } | 1065 | } |
1022 | 1066 | ||
1023 | static void documentRunsInvalidated_DocumentWidget_(iDocumentWidget *d) { | 1067 | static void documentRunsInvalidated_DocumentWidget_(iDocumentWidget *d) { |
1024 | d->foundMark = iNullRange; | 1068 | d->foundMark = iNullRange; |
1025 | d->selectMark = iNullRange; | 1069 | d->selectMark = iNullRange; |
1026 | d->hoverPre = NULL; | 1070 | d->hoverPre = NULL; |
1027 | d->hoverAltPre = NULL; | 1071 | d->hoverAltPre = NULL; |
1028 | d->hoverLink = NULL; | 1072 | d->hoverLink = NULL; |
1029 | d->contextLink = NULL; | 1073 | d->contextLink = NULL; |
1030 | iZap(d->visibleRuns); | 1074 | iZap(d->visibleRuns); |
1031 | iZap(d->renderRuns); | 1075 | iZap(d->renderRuns); |
1032 | } | 1076 | } |
@@ -1087,6 +1131,7 @@ void setSource_DocumentWidget(iDocumentWidget *d, const iString *source) { | |||
1087 | outsideMargin, | 1131 | outsideMargin, |
1088 | isFinished_GmRequest(d->request) ? final_GmDocumentUpdate | 1132 | isFinished_GmRequest(d->request) ? final_GmDocumentUpdate |
1089 | : partial_GmDocumentUpdate); | 1133 | : partial_GmDocumentUpdate); |
1134 | setWidth_Banner(d->banner, docWidth); | ||
1090 | documentWasChanged_DocumentWidget_(d); | 1135 | documentWasChanged_DocumentWidget_(d); |
1091 | } | 1136 | } |
1092 | 1137 | ||
@@ -1097,6 +1142,11 @@ static void replaceDocument_DocumentWidget_(iDocumentWidget *d, iGmDocument *new | |||
1097 | documentWasChanged_DocumentWidget_(d); | 1142 | documentWasChanged_DocumentWidget_(d); |
1098 | } | 1143 | } |
1099 | 1144 | ||
1145 | static void updateBanner_DocumentWidget_(iDocumentWidget *d) { | ||
1146 | clear_Banner(d->banner); | ||
1147 | setSite_Banner(d->banner, siteText_DocumentWidget_(d), siteIcon_GmDocument(d->doc)); | ||
1148 | } | ||
1149 | |||
1100 | static void updateTheme_DocumentWidget_(iDocumentWidget *d) { | 1150 | static void updateTheme_DocumentWidget_(iDocumentWidget *d) { |
1101 | if (equalCase_Rangecc(urlScheme_String(d->mod.url), "file")) { | 1151 | if (equalCase_Rangecc(urlScheme_String(d->mod.url), "file")) { |
1102 | iBlock empty; | 1152 | iBlock empty; |
@@ -1112,8 +1162,10 @@ static void updateTheme_DocumentWidget_(iDocumentWidget *d) { | |||
1112 | setThemeSeed_GmDocument(d->doc, &d->titleUser->chars); | 1162 | setThemeSeed_GmDocument(d->doc, &d->titleUser->chars); |
1113 | } | 1163 | } |
1114 | d->drawBufs->flags |= updateTimestampBuf_DrawBufsFlag; | 1164 | d->drawBufs->flags |= updateTimestampBuf_DrawBufsFlag; |
1165 | updateBanner_DocumentWidget_(d); | ||
1115 | } | 1166 | } |
1116 | 1167 | ||
1168 | #if 0 | ||
1117 | static enum iGmDocumentBanner bannerType_DocumentWidget_(const iDocumentWidget *d) { | 1169 | static enum iGmDocumentBanner bannerType_DocumentWidget_(const iDocumentWidget *d) { |
1118 | if (d->certFlags & available_GmCertFlag) { | 1170 | if (d->certFlags & available_GmCertFlag) { |
1119 | const int req = domainVerified_GmCertFlag | timeVerified_GmCertFlag | trusted_GmCertFlag; | 1171 | const int req = domainVerified_GmCertFlag | timeVerified_GmCertFlag | trusted_GmCertFlag; |
@@ -1123,6 +1175,7 @@ static enum iGmDocumentBanner bannerType_DocumentWidget_(const iDocumentWidget * | |||
1123 | } | 1175 | } |
1124 | return siteDomain_GmDocumentBanner; | 1176 | return siteDomain_GmDocumentBanner; |
1125 | } | 1177 | } |
1178 | #endif | ||
1126 | 1179 | ||
1127 | static void makeFooterButtons_DocumentWidget_(iDocumentWidget *d, const iMenuItem *items, size_t count) { | 1180 | static void makeFooterButtons_DocumentWidget_(iDocumentWidget *d, const iMenuItem *items, size_t count) { |
1128 | iWidget *w = as_Widget(d); | 1181 | iWidget *w = as_Widget(d); |
@@ -1160,6 +1213,8 @@ static void makeFooterButtons_DocumentWidget_(iDocumentWidget *d, const iMenuIte | |||
1160 | 1213 | ||
1161 | static void showErrorPage_DocumentWidget_(iDocumentWidget *d, enum iGmStatusCode code, | 1214 | static void showErrorPage_DocumentWidget_(iDocumentWidget *d, enum iGmStatusCode code, |
1162 | const iString *meta) { | 1215 | const iString *meta) { |
1216 | /* TODO: No such thing as an "error page". It should be an empty page with an error banner. */ | ||
1217 | #if 0 | ||
1163 | iString *src = collectNewCStr_String("# "); | 1218 | iString *src = collectNewCStr_String("# "); |
1164 | const iGmError *msg = get_GmError(code); | 1219 | const iGmError *msg = get_GmError(code); |
1165 | appendChar_String(src, msg->icon ? msg->icon : 0x2327); /* X in a box */ | 1220 | appendChar_String(src, msg->icon ? msg->icon : 0x2327); /* X in a box */ |
@@ -1242,14 +1297,16 @@ static void showErrorPage_DocumentWidget_(iDocumentWidget *d, enum iGmStatusCode | |||
1242 | /* Make a new document for the error page.*/ { | 1297 | /* Make a new document for the error page.*/ { |
1243 | iGmDocument *errorDoc = new_GmDocument(); | 1298 | iGmDocument *errorDoc = new_GmDocument(); |
1244 | setUrl_GmDocument(errorDoc, d->mod.url); | 1299 | setUrl_GmDocument(errorDoc, d->mod.url); |
1245 | setBanner_GmDocument(errorDoc, useBanner ? bannerType_DocumentWidget_(d) : none_GmDocumentBanner); | 1300 | // setBanner_GmDocument(errorDoc, useBanner ? bannerType_DocumentWidget_(d) : none_GmDocumentBanner); |
1301 | |||
1246 | setFormat_GmDocument(errorDoc, gemini_SourceFormat); | 1302 | setFormat_GmDocument(errorDoc, gemini_SourceFormat); |
1247 | replaceDocument_DocumentWidget_(d, errorDoc); | 1303 | replaceDocument_DocumentWidget_(d, errorDoc); |
1248 | iRelease(errorDoc); | 1304 | iRelease(errorDoc); |
1249 | } | 1305 | } |
1250 | translate_Lang(src); | 1306 | translate_Lang(src); |
1307 | #endif | ||
1251 | d->state = ready_RequestState; | 1308 | d->state = ready_RequestState; |
1252 | setSource_DocumentWidget(d, src); | 1309 | // setSource_DocumentWidget(d, src); |
1253 | updateTheme_DocumentWidget_(d); | 1310 | updateTheme_DocumentWidget_(d); |
1254 | reset_SmoothScroll(&d->scrollY); | 1311 | reset_SmoothScroll(&d->scrollY); |
1255 | init_Anim(&d->sideOpacity, 0); | 1312 | init_Anim(&d->sideOpacity, 0); |
@@ -1729,7 +1786,7 @@ static void updateTrust_DocumentWidget_(iDocumentWidget *d, const iGmResponse *r | |||
1729 | else { | 1786 | else { |
1730 | updateTextCStr_LabelWidget(lock, green_ColorEscape closedLock_Icon); | 1787 | updateTextCStr_LabelWidget(lock, green_ColorEscape closedLock_Icon); |
1731 | } | 1788 | } |
1732 | setBanner_GmDocument(d->doc, bannerType_DocumentWidget_(d)); | 1789 | // setBanner_GmDocument(d->doc, bannerType_DocumentWidget_(d)); |
1733 | } | 1790 | } |
1734 | 1791 | ||
1735 | static void parseUser_DocumentWidget_(iDocumentWidget *d) { | 1792 | static void parseUser_DocumentWidget_(iDocumentWidget *d) { |
@@ -1778,12 +1835,13 @@ static void updateFromCachedResponse_DocumentWidget_(iDocumentWidget *d, float n | |||
1778 | updateDocument_DocumentWidget_(d, resp, cachedDoc, iTrue); | 1835 | updateDocument_DocumentWidget_(d, resp, cachedDoc, iTrue); |
1779 | // setCachedDocument_History(d->mod.history, d->doc, | 1836 | // setCachedDocument_History(d->mod.history, d->doc, |
1780 | // (d->flags & openedFromSidebar_DocumentWidgetFlag) != 0); | 1837 | // (d->flags & openedFromSidebar_DocumentWidgetFlag) != 0); |
1838 | updateBanner_DocumentWidget_(d); | ||
1781 | } | 1839 | } |
1782 | d->state = ready_RequestState; | 1840 | d->state = ready_RequestState; |
1783 | postProcessRequestContent_DocumentWidget_(d, iTrue); | 1841 | postProcessRequestContent_DocumentWidget_(d, iTrue); |
1784 | init_Anim(&d->altTextOpacity, 0); | 1842 | init_Anim(&d->altTextOpacity, 0); |
1785 | reset_SmoothScroll(&d->scrollY); | 1843 | reset_SmoothScroll(&d->scrollY); |
1786 | init_Anim(&d->scrollY.pos, d->initNormScrollY * size_GmDocument(d->doc).y); | 1844 | init_Anim(&d->scrollY.pos, d->initNormScrollY * pageHeight_DocumentWidget_(d)); |
1787 | updateSideOpacity_DocumentWidget_(d, iFalse); | 1845 | updateSideOpacity_DocumentWidget_(d, iFalse); |
1788 | updateVisible_DocumentWidget_(d); | 1846 | updateVisible_DocumentWidget_(d); |
1789 | moveSpan_SmoothScroll(&d->scrollY, 0, 0); /* clamp position to new max */ | 1847 | moveSpan_SmoothScroll(&d->scrollY, 0, 0); /* clamp position to new max */ |
@@ -1870,8 +1928,11 @@ static void smoothScroll_DocumentWidget_(iDocumentWidget *d, int offset, int dur | |||
1870 | } | 1928 | } |
1871 | 1929 | ||
1872 | static void scrollTo_DocumentWidget_(iDocumentWidget *d, int documentY, iBool centered) { | 1930 | static void scrollTo_DocumentWidget_(iDocumentWidget *d, int documentY, iBool centered) { |
1873 | if (!hasSiteBanner_GmDocument(d->doc)) { | 1931 | if (!isEmpty_Banner(d->banner)) { |
1874 | documentY += d->pageMargin * gap_UI; | 1932 | documentY += height_Banner(d->banner) + documentTopPad_DocumentWidget_(d); |
1933 | } | ||
1934 | else { | ||
1935 | documentY += documentTopPad_DocumentWidget_(d) + d->pageMargin * gap_UI; | ||
1875 | } | 1936 | } |
1876 | init_Anim(&d->scrollY.pos, | 1937 | init_Anim(&d->scrollY.pos, |
1877 | documentY - (centered ? documentBounds_DocumentWidget_(d).size.y / 2 | 1938 | documentY - (centered ? documentBounds_DocumentWidget_(d).size.y / 2 |
@@ -2403,6 +2464,7 @@ static iBool updateDocumentWidthRetainingScrollPosition_DocumentWidget_(iDocumen | |||
2403 | voffset = visibleRange_DocumentWidget_(d).start - top_Rect(run->visBounds); | 2464 | voffset = visibleRange_DocumentWidget_(d).start - top_Rect(run->visBounds); |
2404 | } | 2465 | } |
2405 | setWidth_GmDocument(d->doc, newWidth, (width_Widget(d) - newWidth) / 2); | 2466 | setWidth_GmDocument(d->doc, newWidth, (width_Widget(d) - newWidth) / 2); |
2467 | setWidth_Banner(d->banner, newWidth); | ||
2406 | documentRunsInvalidated_DocumentWidget_(d); | 2468 | documentRunsInvalidated_DocumentWidget_(d); |
2407 | if (runLoc && !keepCenter) { | 2469 | if (runLoc && !keepCenter) { |
2408 | run = findRunAtLoc_GmDocument(d->doc, runLoc); | 2470 | run = findRunAtLoc_GmDocument(d->doc, runLoc); |
@@ -2504,7 +2566,8 @@ static iBool handleSwipe_DocumentWidget_(iDocumentWidget *d, const char *cmd) { | |||
2504 | if (recent->cachedDoc) { | 2566 | if (recent->cachedDoc) { |
2505 | iChangeRef(swipeIn->doc, recent->cachedDoc); | 2567 | iChangeRef(swipeIn->doc, recent->cachedDoc); |
2506 | updateScrollMax_DocumentWidget_(d); | 2568 | updateScrollMax_DocumentWidget_(d); |
2507 | setValue_Anim(&swipeIn->scrollY.pos, size_GmDocument(swipeIn->doc).y * recent->normScrollY, 0); | 2569 | setValue_Anim(&swipeIn->scrollY.pos, |
2570 | pageHeight_DocumentWidget_(d) * recent->normScrollY, 0); | ||
2508 | updateVisible_DocumentWidget_(swipeIn); | 2571 | updateVisible_DocumentWidget_(swipeIn); |
2509 | swipeIn->drawBufs->flags |= updateTimestampBuf_DrawBufsFlag | updateSideBuf_DrawBufsFlag; | 2572 | swipeIn->drawBufs->flags |= updateTimestampBuf_DrawBufsFlag | updateSideBuf_DrawBufsFlag; |
2510 | } | 2573 | } |
@@ -2935,7 +2998,7 @@ static iBool handleCommand_DocumentWidget_(iDocumentWidget *d, const char *cmd) | |||
2935 | updateFetchProgress_DocumentWidget_(d); | 2998 | updateFetchProgress_DocumentWidget_(d); |
2936 | checkResponse_DocumentWidget_(d); | 2999 | checkResponse_DocumentWidget_(d); |
2937 | if (category_GmStatusCode(status_GmRequest(d->request)) == categorySuccess_GmStatusCode) { | 3000 | if (category_GmStatusCode(status_GmRequest(d->request)) == categorySuccess_GmStatusCode) { |
2938 | init_Anim(&d->scrollY.pos, d->initNormScrollY * size_GmDocument(d->doc).y); /* TODO: unless user already scrolled! */ | 3001 | init_Anim(&d->scrollY.pos, d->initNormScrollY * pageHeight_DocumentWidget_(d)); /* TODO: unless user already scrolled! */ |
2939 | } | 3002 | } |
2940 | iChangeFlags(d->flags, | 3003 | iChangeFlags(d->flags, |
2941 | urlChanged_DocumentWidgetFlag | drawDownloadCounter_DocumentWidgetFlag, | 3004 | urlChanged_DocumentWidgetFlag | drawDownloadCounter_DocumentWidgetFlag, |
@@ -3352,7 +3415,7 @@ static iBool handleCommand_DocumentWidget_(iDocumentWidget *d, const char *cmd) | |||
3352 | 3415 | ||
3353 | static iRect runRect_DocumentWidget_(const iDocumentWidget *d, const iGmRun *run) { | 3416 | static iRect runRect_DocumentWidget_(const iDocumentWidget *d, const iGmRun *run) { |
3354 | const iRect docBounds = documentBounds_DocumentWidget_(d); | 3417 | const iRect docBounds = documentBounds_DocumentWidget_(d); |
3355 | return moved_Rect(run->bounds, addY_I2(topLeft_Rect(docBounds), -pos_SmoothScroll(&d->scrollY))); | 3418 | return moved_Rect(run->bounds, addY_I2(topLeft_Rect(docBounds), viewPos_DocumentWidget_(d))); |
3356 | } | 3419 | } |
3357 | 3420 | ||
3358 | static void setGrabbedPlayer_DocumentWidget_(iDocumentWidget *d, const iGmRun *run) { | 3421 | static void setGrabbedPlayer_DocumentWidget_(iDocumentWidget *d, const iGmRun *run) { |
@@ -3660,9 +3723,11 @@ static iBool processEvent_DocumentWidget_(iDocumentWidget *d, const SDL_Event *e | |||
3660 | if (isVisible_Widget(d->menu)) { | 3723 | if (isVisible_Widget(d->menu)) { |
3661 | setCursor_Window(get_Window(), SDL_SYSTEM_CURSOR_ARROW); | 3724 | setCursor_Window(get_Window(), SDL_SYSTEM_CURSOR_ARROW); |
3662 | } | 3725 | } |
3726 | #if 0 | ||
3663 | else if (contains_Rect(siteBannerRect_DocumentWidget_(d), mpos)) { | 3727 | else if (contains_Rect(siteBannerRect_DocumentWidget_(d), mpos)) { |
3664 | setCursor_Window(get_Window(), SDL_SYSTEM_CURSOR_HAND); | 3728 | setCursor_Window(get_Window(), SDL_SYSTEM_CURSOR_HAND); |
3665 | } | 3729 | } |
3730 | #endif | ||
3666 | else { | 3731 | else { |
3667 | if (value_Anim(&d->altTextOpacity) < 0.833f) { | 3732 | if (value_Anim(&d->altTextOpacity) < 0.833f) { |
3668 | setValue_Anim(&d->altTextOpacity, 0, 0); /* keep it hidden while moving */ | 3733 | setValue_Anim(&d->altTextOpacity, 0, 0); /* keep it hidden while moving */ |
@@ -4126,6 +4191,7 @@ static iBool processEvent_DocumentWidget_(iDocumentWidget *d, const SDL_Event *e | |||
4126 | d->selectMark = iNullRange; | 4191 | d->selectMark = iNullRange; |
4127 | refresh_Widget(w); | 4192 | refresh_Widget(w); |
4128 | } | 4193 | } |
4194 | #if 0 | ||
4129 | /* Clicking on the top/side banner navigates to site root. */ | 4195 | /* Clicking on the top/side banner navigates to site root. */ |
4130 | const iRect banRect = siteBannerRect_DocumentWidget_(d); | 4196 | const iRect banRect = siteBannerRect_DocumentWidget_(d); |
4131 | if (contains_Rect(banRect, pos_Click(&d->click))) { | 4197 | if (contains_Rect(banRect, pos_Click(&d->click))) { |
@@ -4139,6 +4205,7 @@ static iBool processEvent_DocumentWidget_(iDocumentWidget *d, const SDL_Event *e | |||
4139 | postCommand_Widget(d, "navigate.root"); | 4205 | postCommand_Widget(d, "navigate.root"); |
4140 | } | 4206 | } |
4141 | } | 4207 | } |
4208 | #endif | ||
4142 | } | 4209 | } |
4143 | return iTrue; | 4210 | return iTrue; |
4144 | case aborted_ClickResult: | 4211 | case aborted_ClickResult: |
@@ -4200,7 +4267,7 @@ static void fillRange_DrawContext_(iDrawContext *d, const iGmRun *run, enum iCol | |||
4200 | } | 4267 | } |
4201 | if (~run->flags & decoration_GmRunFlag) { | 4268 | if (~run->flags & decoration_GmRunFlag) { |
4202 | const iInt2 visPos = | 4269 | const iInt2 visPos = |
4203 | add_I2(run->bounds.pos, addY_I2(d->viewPos, -pos_SmoothScroll(&d->widget->scrollY))); | 4270 | add_I2(run->bounds.pos, addY_I2(d->viewPos, viewPos_DocumentWidget_(d->widget))); |
4204 | const iRect rangeRect = { addX_I2(visPos, x), init_I2(w, height_Rect(run->bounds)) }; | 4271 | const iRect rangeRect = { addX_I2(visPos, x), init_I2(w, height_Rect(run->bounds)) }; |
4205 | if (rangeRect.size.x) { | 4272 | if (rangeRect.size.x) { |
4206 | fillRect_Paint(&d->paint, rangeRect, color); | 4273 | fillRect_Paint(&d->paint, rangeRect, color); |
@@ -4220,7 +4287,7 @@ static void fillRange_DrawContext_(iDrawContext *d, const iGmRun *run, enum iCol | |||
4220 | (contains_Range(&url, mark.end) || url.end == mark.end)) { | 4287 | (contains_Range(&url, mark.end) || url.end == mark.end)) { |
4221 | fillRect_Paint( | 4288 | fillRect_Paint( |
4222 | &d->paint, | 4289 | &d->paint, |
4223 | moved_Rect(run->visBounds, addY_I2(d->viewPos, -pos_SmoothScroll(&d->widget->scrollY))), | 4290 | moved_Rect(run->visBounds, addY_I2(d->viewPos, viewPos_DocumentWidget_(d->widget))), |
4224 | color); | 4291 | color); |
4225 | } | 4292 | } |
4226 | } | 4293 | } |
@@ -4234,96 +4301,6 @@ static void drawMark_DrawContext_(void *context, const iGmRun *run) { | |||
4234 | } | 4301 | } |
4235 | } | 4302 | } |
4236 | 4303 | ||
4237 | static void drawBannerRun_DrawContext_(iDrawContext *d, const iGmRun *run, iInt2 visPos) { | ||
4238 | const iGmDocument *doc = d->widget->doc; | ||
4239 | const iChar icon = siteIcon_GmDocument(doc); | ||
4240 | iString str; | ||
4241 | init_String(&str); | ||
4242 | iInt2 bpos = add_I2(visPos, init_I2(0, lineHeight_Text(banner_FontId) / 2)); | ||
4243 | if (icon) { | ||
4244 | appendChar_String(&str, icon); | ||
4245 | const iRect iconRect = visualBounds_Text(run->font, range_String(&str)); | ||
4246 | drawRange_Text( | ||
4247 | run->font, | ||
4248 | addY_I2(bpos, -mid_Rect(iconRect).y + lineHeight_Text(run->font) / 2), | ||
4249 | tmBannerIcon_ColorId, | ||
4250 | range_String(&str)); | ||
4251 | bpos.x += right_Rect(iconRect) + 3 * gap_Text; | ||
4252 | } | ||
4253 | drawRange_Text(run->font, | ||
4254 | bpos, | ||
4255 | tmBannerTitle_ColorId, | ||
4256 | bannerText_DocumentWidget_(d->widget)); | ||
4257 | if (bannerType_GmDocument(doc) == certificateWarning_GmDocumentBanner) { | ||
4258 | const int domainHeight = lineHeight_Text(banner_FontId) * 2; | ||
4259 | iRect rect = { add_I2(visPos, init_I2(0, domainHeight)), | ||
4260 | addY_I2(run->visBounds.size, -domainHeight - lineHeight_Text(uiContent_FontId)) }; | ||
4261 | format_String(&str, "${heading.certwarn}"); | ||
4262 | const int certFlags = d->widget->certFlags; | ||
4263 | if (certFlags & timeVerified_GmCertFlag && certFlags & domainVerified_GmCertFlag) { | ||
4264 | iUrl parts; | ||
4265 | init_Url(&parts, d->widget->mod.url); | ||
4266 | const iTime oldUntil = | ||
4267 | domainValidUntil_GmCerts(certs_App(), parts.host, port_Url(&parts)); | ||
4268 | iDate exp; | ||
4269 | init_Date(&exp, &oldUntil); | ||
4270 | iTime now; | ||
4271 | initCurrent_Time(&now); | ||
4272 | const int days = secondsSince_Time(&oldUntil, &now) / 3600 / 24; | ||
4273 | appendCStr_String(&str, "\n"); | ||
4274 | if (days <= 30) { | ||
4275 | appendCStr_String(&str, | ||
4276 | format_CStr(cstrCount_Lang("dlg.certwarn.mayberenewed.n", days), | ||
4277 | cstrCollect_String(format_Date(&exp, "%Y-%m-%d")), | ||
4278 | days)); | ||
4279 | } | ||
4280 | else { | ||
4281 | appendCStr_String(&str, cstr_Lang("dlg.certwarn.different")); | ||
4282 | } | ||
4283 | } | ||
4284 | else if (certFlags & domainVerified_GmCertFlag) { | ||
4285 | appendCStr_String(&str, "\n"); | ||
4286 | appendFormat_String(&str, cstr_Lang("dlg.certwarn.expired"), | ||
4287 | cstrCollect_String(format_Date(&d->widget->certExpiry, "%Y-%m-%d"))); | ||
4288 | } | ||
4289 | else if (certFlags & timeVerified_GmCertFlag) { | ||
4290 | appendCStr_String(&str, "\n"); | ||
4291 | appendFormat_String(&str, cstr_Lang("dlg.certwarn.domain"), | ||
4292 | cstr_String(d->widget->certSubject)); | ||
4293 | } | ||
4294 | else { | ||
4295 | appendCStr_String(&str, "\n"); | ||
4296 | appendCStr_String(&str, cstr_Lang("dlg.certwarn.domain.expired")); | ||
4297 | } | ||
4298 | const iInt2 dims = measureWrapRange_Text( | ||
4299 | uiContent_FontId, width_Rect(rect) - 16 * gap_UI, range_String(&str)).bounds.size; | ||
4300 | const int warnHeight = run->visBounds.size.y - domainHeight; | ||
4301 | const int yOff = (lineHeight_Text(uiLabelLarge_FontId) - | ||
4302 | lineHeight_Text(uiContent_FontId)) / 2; | ||
4303 | const iRect bgRect = | ||
4304 | init_Rect(0, visPos.y + domainHeight, d->widgetBounds.size.x, warnHeight); | ||
4305 | fillRect_Paint(&d->paint, bgRect, orange_ColorId); | ||
4306 | if (!isDark_ColorTheme(colorTheme_App())) { | ||
4307 | drawHLine_Paint(&d->paint, | ||
4308 | topLeft_Rect(bgRect), width_Rect(bgRect), tmBannerTitle_ColorId); | ||
4309 | drawHLine_Paint(&d->paint, | ||
4310 | bottomLeft_Rect(bgRect), width_Rect(bgRect), tmBannerTitle_ColorId); | ||
4311 | } | ||
4312 | const int fg = black_ColorId; | ||
4313 | adjustEdges_Rect(&rect, warnHeight / 2 - dims.y / 2 - yOff, 0, 0, 0); | ||
4314 | bpos = topLeft_Rect(rect); | ||
4315 | draw_Text(uiLabelLarge_FontId, bpos, fg, "\u26a0"); | ||
4316 | adjustEdges_Rect(&rect, 0, -8 * gap_UI, 0, 8 * gap_UI); | ||
4317 | translate_Lang(&str); | ||
4318 | drawWrapRange_Text(uiContent_FontId, | ||
4319 | addY_I2(topLeft_Rect(rect), yOff), | ||
4320 | width_Rect(rect), | ||
4321 | fg, | ||
4322 | range_String(&str)); | ||
4323 | } | ||
4324 | deinit_String(&str); | ||
4325 | } | ||
4326 | |||
4327 | static void drawRun_DrawContext_(void *context, const iGmRun *run) { | 4304 | static void drawRun_DrawContext_(void *context, const iGmRun *run) { |
4328 | iDrawContext *d = context; | 4305 | iDrawContext *d = context; |
4329 | const iInt2 origin = d->viewPos; | 4306 | const iInt2 origin = d->viewPos; |
@@ -4430,6 +4407,7 @@ static void drawRun_DrawContext_(void *context, const iGmRun *run) { | |||
4430 | run->color, | 4407 | run->color, |
4431 | run->text); | 4408 | run->text); |
4432 | } | 4409 | } |
4410 | #if 0 | ||
4433 | else if (run->flags & siteBanner_GmRunFlag) { | 4411 | else if (run->flags & siteBanner_GmRunFlag) { |
4434 | /* Banner background. */ | 4412 | /* Banner background. */ |
4435 | iRect bannerBack = initCorners_Rect(topLeft_Rect(d->widgetBounds), | 4413 | iRect bannerBack = initCorners_Rect(topLeft_Rect(d->widgetBounds), |
@@ -4438,6 +4416,7 @@ static void drawRun_DrawContext_(void *context, const iGmRun *run) { | |||
4438 | fillRect_Paint(&d->paint, bannerBack, tmBannerBackground_ColorId); | 4416 | fillRect_Paint(&d->paint, bannerBack, tmBannerBackground_ColorId); |
4439 | drawBannerRun_DrawContext_(d, run, visPos); | 4417 | drawBannerRun_DrawContext_(d, run, visPos); |
4440 | } | 4418 | } |
4419 | #endif | ||
4441 | else { | 4420 | else { |
4442 | if (d->showLinkNumbers && run->linkId && run->flags & decoration_GmRunFlag) { | 4421 | if (d->showLinkNumbers && run->linkId && run->flags & decoration_GmRunFlag) { |
4443 | const size_t ord = visibleLinkOrdinal_DocumentWidget_(d->widget, run->linkId); | 4422 | const size_t ord = visibleLinkOrdinal_DocumentWidget_(d->widget, run->linkId); |
@@ -4663,8 +4642,8 @@ static void updateSideIconBuf_DocumentWidget_(const iDocumentWidget *d) { | |||
4663 | SDL_DestroyTexture(dbuf->sideIconBuf); | 4642 | SDL_DestroyTexture(dbuf->sideIconBuf); |
4664 | dbuf->sideIconBuf = NULL; | 4643 | dbuf->sideIconBuf = NULL; |
4665 | } | 4644 | } |
4666 | const iGmRun *banner = siteBanner_GmDocument(d->doc); | 4645 | // const iGmRun *banner = siteBanner_GmDocument(d->doc); |
4667 | if (!banner) { | 4646 | if (isEmpty_Banner(d->banner)) { |
4668 | return; | 4647 | return; |
4669 | } | 4648 | } |
4670 | const int margin = gap_UI * d->pageMargin; | 4649 | const int margin = gap_UI * d->pageMargin; |
@@ -4747,7 +4726,7 @@ static void drawSideElements_DocumentWidget_(const iDocumentWidget *d) { | |||
4747 | bottomLeft_Rect(bounds), | 4726 | bottomLeft_Rect(bounds), |
4748 | init_I2(margin, | 4727 | init_I2(margin, |
4749 | -margin + -dbuf->timestampBuf->size.y + | 4728 | -margin + -dbuf->timestampBuf->size.y + |
4750 | iMax(0, d->scrollY.max - pos_SmoothScroll(&d->scrollY)))), | 4729 | iMax(0, d->scrollY.max + viewPos_DocumentWidget_(d)))), |
4751 | tmQuoteIcon_ColorId); | 4730 | tmQuoteIcon_ColorId); |
4752 | } | 4731 | } |
4753 | unsetClip_Paint(&p); | 4732 | unsetClip_Paint(&p); |
@@ -4988,7 +4967,7 @@ static void draw_DocumentWidget_(const iDocumentWidget *d) { | |||
4988 | }; | 4967 | }; |
4989 | init_Paint(&ctx.paint); | 4968 | init_Paint(&ctx.paint); |
4990 | render_DocumentWidget_(d, &ctx, iFalse /* just the mandatory parts */); | 4969 | render_DocumentWidget_(d, &ctx, iFalse /* just the mandatory parts */); |
4991 | int yTop = docBounds.pos.y - pos_SmoothScroll(&d->scrollY); | 4970 | int yTop = docBounds.pos.y + viewPos_DocumentWidget_(d); |
4992 | const iBool isDocEmpty = size_GmDocument(d->doc).y == 0; | 4971 | const iBool isDocEmpty = size_GmDocument(d->doc).y == 0; |
4993 | const iBool isTouchSelecting = (flags_Widget(w) & touchDrag_WidgetFlag) != 0; | 4972 | const iBool isTouchSelecting = (flags_Widget(w) & touchDrag_WidgetFlag) != 0; |
4994 | if (!isDocEmpty) { | 4973 | if (!isDocEmpty) { |
@@ -5025,12 +5004,22 @@ static void draw_DocumentWidget_(const iDocumentWidget *d) { | |||
5025 | } | 5004 | } |
5026 | } | 5005 | } |
5027 | drawMedia_DocumentWidget_(d, &ctx.paint); | 5006 | drawMedia_DocumentWidget_(d, &ctx.paint); |
5028 | /* Fill the top and bottom, in case the document is short. */ | 5007 | /* Fill the top and bottom, in case the document is short. */ |
5029 | if (yTop > top_Rect(bounds)) { | 5008 | if (yTop > top_Rect(bounds)) { |
5030 | fillRect_Paint(&ctx.paint, | 5009 | fillRect_Paint(&ctx.paint, |
5031 | (iRect){ bounds.pos, init_I2(bounds.size.x, yTop - top_Rect(bounds)) }, | 5010 | (iRect){ bounds.pos, init_I2(bounds.size.x, yTop - top_Rect(bounds)) }, |
5032 | hasSiteBanner_GmDocument(d->doc) ? tmBannerBackground_ColorId | 5011 | !isEmpty_Banner(d->banner) ? tmBannerBackground_ColorId |
5033 | : tmBackground_ColorId); | 5012 | : tmBackground_ColorId); |
5013 | } | ||
5014 | /* Banner. */ { | ||
5015 | /* Fill the part between the banner and the top of the document. */ | ||
5016 | fillRect_Paint(&ctx.paint, | ||
5017 | (iRect){ init_I2(left_Rect(bounds), | ||
5018 | top_Rect(docBounds) + viewPos_DocumentWidget_(d) - | ||
5019 | documentTopPad_DocumentWidget_(d)), | ||
5020 | init_I2(bounds.size.x, documentTopPad_DocumentWidget_(d)) }, | ||
5021 | tmBackground_ColorId); | ||
5022 | draw_Banner(d->banner); | ||
5034 | } | 5023 | } |
5035 | const int yBottom = yTop + size_GmDocument(d->doc).y + 1; | 5024 | const int yBottom = yTop + size_GmDocument(d->doc).y + 1; |
5036 | if (yBottom < bottom_Rect(bounds)) { | 5025 | if (yBottom < bottom_Rect(bounds)) { |
@@ -5073,7 +5062,7 @@ static void draw_DocumentWidget_(const iDocumentWidget *d) { | |||
5073 | const int altFont = uiLabel_FontId; | 5062 | const int altFont = uiLabel_FontId; |
5074 | const int wrap = docBounds.size.x - 2 * margin; | 5063 | const int wrap = docBounds.size.x - 2 * margin; |
5075 | iInt2 pos = addY_I2(add_I2(docBounds.pos, meta->pixelRect.pos), | 5064 | iInt2 pos = addY_I2(add_I2(docBounds.pos, meta->pixelRect.pos), |
5076 | -pos_SmoothScroll(&d->scrollY)); | 5065 | viewPos_DocumentWidget_(d)); |
5077 | const iInt2 textSize = measureWrapRange_Text(altFont, wrap, meta->altText).bounds.size; | 5066 | const iInt2 textSize = measureWrapRange_Text(altFont, wrap, meta->altText).bounds.size; |
5078 | pos.y -= textSize.y + gap_UI; | 5067 | pos.y -= textSize.y + gap_UI; |
5079 | pos.y = iMax(pos.y, top_Rect(bounds)); | 5068 | pos.y = iMax(pos.y, top_Rect(bounds)); |
@@ -5276,11 +5265,23 @@ void updateSize_DocumentWidget(iDocumentWidget *d) { | |||
5276 | resetWideRuns_DocumentWidget_(d); | 5265 | resetWideRuns_DocumentWidget_(d); |
5277 | d->drawBufs->flags |= updateSideBuf_DrawBufsFlag; | 5266 | d->drawBufs->flags |= updateSideBuf_DrawBufsFlag; |
5278 | updateVisible_DocumentWidget_(d); | 5267 | updateVisible_DocumentWidget_(d); |
5268 | setWidth_Banner(d->banner, documentWidth_DocumentWidget(d)); | ||
5279 | invalidate_DocumentWidget_(d); | 5269 | invalidate_DocumentWidget_(d); |
5280 | arrange_Widget(d->footerButtons); | 5270 | arrange_Widget(d->footerButtons); |
5281 | } | 5271 | } |
5282 | 5272 | ||
5273 | #if 0 | ||
5274 | static void sizeChanged_DocumentWidget_(iDocumentWidget *d) { | ||
5275 | if (current_Root()) { | ||
5276 | /* TODO: This gets called more than once during a single arrange. | ||
5277 | It could be done via some sort of callback instead. */ | ||
5278 | updateVisible_DocumentWidget_(d); | ||
5279 | } | ||
5280 | } | ||
5281 | #endif | ||
5282 | |||
5283 | iBeginDefineSubclass(DocumentWidget, Widget) | 5283 | iBeginDefineSubclass(DocumentWidget, Widget) |
5284 | .processEvent = (iAny *) processEvent_DocumentWidget_, | 5284 | .processEvent = (iAny *) processEvent_DocumentWidget_, |
5285 | .draw = (iAny *) draw_DocumentWidget_, | 5285 | .draw = (iAny *) draw_DocumentWidget_, |
5286 | // .sizeChanged = (iAny *) sizeChanged_DocumentWidget_, | ||
5286 | iEndDefineSubclass(DocumentWidget) | 5287 | iEndDefineSubclass(DocumentWidget) |