summaryrefslogtreecommitdiff
path: root/src/ui
diff options
context:
space:
mode:
authorJaakko Keränen <jaakko.keranen@iki.fi>2020-09-26 13:51:14 +0300
committerJaakko Keränen <jaakko.keranen@iki.fi>2020-09-26 13:51:14 +0300
commit1449337bde58999838b34edcaf998d72b2eb1f32 (patch)
treef99c2f9f30643606dd0f093d8b9755bbd7dc5689 /src/ui
parent790a2c49a0290ce872ec8929b063337eacde9880 (diff)
DocumentWidget: Show top heading on the side
Diffstat (limited to 'src/ui')
-rw-r--r--src/ui/documentwidget.c94
1 files changed, 60 insertions, 34 deletions
diff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c
index ec6288d5..3fbedb9a 100644
--- a/src/ui/documentwidget.c
+++ b/src/ui/documentwidget.c
@@ -173,6 +173,7 @@ struct Impl_DocumentWidget {
173 const iGmRun * contextLink; 173 const iGmRun * contextLink;
174 iBool noHoverWhileScrolling; 174 iBool noHoverWhileScrolling;
175 iBool showLinkNumbers; 175 iBool showLinkNumbers;
176 const iGmRun * firstVisibleRun;
176 const iGmRun * lastVisibleRun; 177 const iGmRun * lastVisibleRun;
177 iClick click; 178 iClick click;
178 float initNormScrollY; 179 float initNormScrollY;
@@ -222,6 +223,7 @@ void init_DocumentWidget(iDocumentWidget *d) {
222 d->contextLink = NULL; 223 d->contextLink = NULL;
223 d->noHoverWhileScrolling = iFalse; 224 d->noHoverWhileScrolling = iFalse;
224 d->showLinkNumbers = iFalse; 225 d->showLinkNumbers = iFalse;
226 d->firstVisibleRun = NULL;
225 d->lastVisibleRun = NULL; 227 d->lastVisibleRun = NULL;
226 d->visBuf = new_VisBuf(); 228 d->visBuf = new_VisBuf();
227 d->invalidRuns = new_PtrSet(); 229 d->invalidRuns = new_PtrSet();
@@ -332,7 +334,12 @@ static iRangei visibleRange_DocumentWidget_(const iDocumentWidget *d) {
332 334
333static void addVisibleLink_DocumentWidget_(void *context, const iGmRun *run) { 335static void addVisibleLink_DocumentWidget_(void *context, const iGmRun *run) {
334 iDocumentWidget *d = context; 336 iDocumentWidget *d = context;
335 d->lastVisibleRun = run; 337 if (~run->flags & decoration_GmRunFlag && !run->imageId) {
338 if (!d->firstVisibleRun) {
339 d->firstVisibleRun = run;
340 }
341 d->lastVisibleRun = run;
342 }
336 if (run->linkId && linkFlags_GmDocument(d->doc, run->linkId) & supportedProtocol_GmLinkFlag) { 343 if (run->linkId && linkFlags_GmDocument(d->doc, run->linkId) & supportedProtocol_GmLinkFlag) {
337 pushBack_PtrArray(&d->visibleLinks, run); 344 pushBack_PtrArray(&d->visibleLinks, run);
338 } 345 }
@@ -422,7 +429,7 @@ static void updateOutlineOpacity_DocumentWidget_(iDocumentWidget *d) {
422 if (contains_Widget(constAs_Widget(d->scroll), mouseCoord_Window(get_Window()))) { 429 if (contains_Widget(constAs_Widget(d->scroll), mouseCoord_Window(get_Window()))) {
423 opacity = 1.0f; 430 opacity = 1.0f;
424 } 431 }
425 setValue_Anim(&d->outlineOpacity, opacity, opacity > 0.5f? 166 : 333); 432 setValue_Anim(&d->outlineOpacity, opacity, opacity > 0.5f? 100 : 166);
426 animate_DocumentWidget_(d); 433 animate_DocumentWidget_(d);
427} 434}
428 435
@@ -435,6 +442,7 @@ static void updateVisible_DocumentWidget_(iDocumentWidget *d) {
435 d->scrollY, 442 d->scrollY,
436 docSize > 0 ? height_Rect(bounds) * size_Range(&visRange) / docSize : 0); 443 docSize > 0 ? height_Rect(bounds) * size_Range(&visRange) / docSize : 0);
437 clear_PtrArray(&d->visibleLinks); 444 clear_PtrArray(&d->visibleLinks);
445 d->firstVisibleRun = NULL;
438 render_GmDocument(d->doc, visRange, addVisibleLink_DocumentWidget_, d); 446 render_GmDocument(d->doc, visRange, addVisibleLink_DocumentWidget_, d);
439 updateHover_DocumentWidget_(d, mouseCoord_Window(get_Window())); 447 updateHover_DocumentWidget_(d, mouseCoord_Window(get_Window()));
440 updateSideOpacity_DocumentWidget_(d); 448 updateSideOpacity_DocumentWidget_(d);
@@ -1496,6 +1504,11 @@ static iBool handleCommand_DocumentWidget_(iDocumentWidget *d, const char *cmd)
1496 return iFalse; 1504 return iFalse;
1497} 1505}
1498 1506
1507static int outlineHeight_DocumentWidget_(const iDocumentWidget *d) {
1508 if (isEmpty_Array(&d->outline)) return 0;
1509 return bottom_Rect(((const iOutlineItem *) constBack_Array(&d->outline))->rect);
1510}
1511
1499static size_t visibleLinkOrdinal_DocumentWidget_(const iDocumentWidget *d, iGmLinkId linkId) { 1512static size_t visibleLinkOrdinal_DocumentWidget_(const iDocumentWidget *d, iGmLinkId linkId) {
1500 size_t ord = 0; 1513 size_t ord = 0;
1501 const iRangei visRange = visibleRange_DocumentWidget_(d); 1514 const iRangei visRange = visibleRange_DocumentWidget_(d);
@@ -1632,9 +1645,17 @@ static iBool processEvent_DocumentWidget_(iDocumentWidget *d, const SDL_Event *e
1632 } 1645 }
1633 } 1646 }
1634 else if (ev->type == SDL_MOUSEWHEEL && isHover_Widget(w)) { 1647 else if (ev->type == SDL_MOUSEWHEEL && isHover_Widget(w)) {
1648 float acceleration = 1.0f;
1649 if (prefs_App()->hoverOutline &&
1650 contains_Widget(constAs_Widget(d->scroll), mouseCoord_Window(get_Window()))) {
1651 const int outHeight = outlineHeight_DocumentWidget_(d);
1652 if (outHeight > height_Rect(bounds_Widget(w))) {
1653 acceleration = (float) size_GmDocument(d->doc).y / (float) outHeight;
1654 }
1655 }
1635#if defined (iPlatformApple) 1656#if defined (iPlatformApple)
1636 /* Momentum scrolling. */ 1657 /* Momentum scrolling. */
1637 scroll_DocumentWidget_(d, -ev->wheel.y * get_Window()->pixelRatio); 1658 scroll_DocumentWidget_(d, -ev->wheel.y * get_Window()->pixelRatio * acceleration);
1638#else 1659#else
1639 if (keyMods_Sym(SDL_GetModState()) == KMOD_PRIMARY) { 1660 if (keyMods_Sym(SDL_GetModState()) == KMOD_PRIMARY) {
1640 postCommandf_App("zoom.delta arg:%d", ev->wheel.y > 0 ? 10 : -10); 1661 postCommandf_App("zoom.delta arg:%d", ev->wheel.y > 0 ? 10 : -10);
@@ -1642,7 +1663,7 @@ static iBool processEvent_DocumentWidget_(iDocumentWidget *d, const SDL_Event *e
1642 } 1663 }
1643 smoothScroll_DocumentWidget_( 1664 smoothScroll_DocumentWidget_(
1644 d, 1665 d,
1645 -3 * ev->wheel.y * lineHeight_Text(paragraph_FontId), 1666 -3 * ev->wheel.y * lineHeight_Text(paragraph_FontId) * acceleration,
1646 gap_Text * smoothSpeed_DocumentWidget_ + 1667 gap_Text * smoothSpeed_DocumentWidget_ +
1647 (isSmoothScrolling_DocumentWidget_(d) ? d->smoothSpeed : 0)); 1668 (isSmoothScrolling_DocumentWidget_(d) ? d->smoothSpeed : 0));
1648#endif 1669#endif
@@ -2069,6 +2090,24 @@ static int drawSideRect_(iPaint *p, iRect rect) { //}, int thickness) {
2069 return fg; 2090 return fg;
2070} 2091}
2071 2092
2093static iRangecc currentHeading_DocumentWidget_(const iDocumentWidget *d) {
2094 iRangecc heading = iNullRange;
2095 if (d->firstVisibleRun) {
2096 iConstForEach(Array, i, headings_GmDocument(d->doc)) {
2097 const iGmHeading *head = i.value;
2098 if (head->level == 0) {
2099 if (head->text.start <= d->firstVisibleRun->text.start) {
2100 heading = head->text;
2101 }
2102 if (d->lastVisibleRun && head->text.start > d->lastVisibleRun->text.start) {
2103 break;
2104 }
2105 }
2106 }
2107 }
2108 return heading;
2109}
2110
2072static void drawSideElements_DocumentWidget_(const iDocumentWidget *d) { 2111static void drawSideElements_DocumentWidget_(const iDocumentWidget *d) {
2073 const iWidget *w = constAs_Widget(d); 2112 const iWidget *w = constAs_Widget(d);
2074 const iRect bounds = bounds_Widget(w); 2113 const iRect bounds = bounds_Widget(w);
@@ -2090,22 +2129,18 @@ static void drawSideElements_DocumentWidget_(const iDocumentWidget *d) {
2090 p.alpha = opacity * 255; 2129 p.alpha = opacity * 255;
2091 //int offset = iMax(0, bottom_Rect(banner->visBounds) - d->scrollY); 2130 //int offset = iMax(0, bottom_Rect(banner->visBounds) - d->scrollY);
2092 rect.pos.y += height_Rect(bounds) / 2 - rect.size.y / 2 - (banner ? banner->visBounds.size.y / 2 : 0); // offset; 2131 rect.pos.y += height_Rect(bounds) / 2 - rect.size.y / 2 - (banner ? banner->visBounds.size.y / 2 : 0); // offset;
2132 //rect.pos.y -= lineHeight_Text(heading3_FontId) / 2; /* the heading text underneath */
2093 int fg = drawSideRect_(&p, rect); //, gap_UI / 2); 2133 int fg = drawSideRect_(&p, rect); //, gap_UI / 2);
2094// if (equal_Color(get_Color(tmBannerBackground_ColorId), get_Color(tmBackground_ColorId))) {
2095// drawRectThickness_Paint(&p, rect, gap_UI / 2, tmBannerIcon_ColorId);
2096// }
2097// else {
2098// fillRect_Paint(&p, rect, tmBannerBackground_ColorId);
2099// }
2100 iString str; 2134 iString str;
2101 initUnicodeN_String(&str, &icon, 1); 2135 initUnicodeN_String(&str, &icon, 1);
2102 drawCentered_Text(banner_FontId, rect, iTrue, fg, "%s", cstr_String(&str)); 2136 drawCentered_Text(banner_FontId, rect, iTrue, fg, "%s", cstr_String(&str));
2103#if 0 2137#if 1
2104 if (avail >= minBannerSize * 2) { 2138 if (avail >= minBannerSize * 2.25f) {
2105 const char *endp; 2139 iRangecc text = currentHeading_DocumentWidget_(d);// bannerText_DocumentWidget_(d);
2106 iRangecc text = bannerText_DocumentWidget_(d);
2107 iInt2 pos = addY_I2(bottomLeft_Rect(rect), gap_Text); 2140 iInt2 pos = addY_I2(bottomLeft_Rect(rect), gap_Text);
2108 const int font = heading3_FontId; 2141 const int font = heading3_FontId;
2142 drawWrapRange_Text(font, pos, avail - margin, tmBannerSideTitle_ColorId, text);
2143#if 0
2109 while (!isEmpty_Range(&text)) { 2144 while (!isEmpty_Range(&text)) {
2110 tryAdvance_Text(font, text, avail - 2 * margin, &endp); 2145 tryAdvance_Text(font, text, avail - 2 * margin, &endp);
2111 drawRange_Text( 2146 drawRange_Text(
@@ -2117,6 +2152,7 @@ static void drawSideElements_DocumentWidget_(const iDocumentWidget *d) {
2117 text.start = endp; 2152 text.start = endp;
2118 pos.y += lineHeight_Text(font); 2153 pos.y += lineHeight_Text(font);
2119 } 2154 }
2155#endif
2120 } 2156 }
2121#endif 2157#endif
2122 setOpacity_Text(1.0f); 2158 setOpacity_Text(1.0f);
@@ -2142,31 +2178,21 @@ static void drawSideElements_DocumentWidget_(const iDocumentWidget *d) {
2142 /* Outline on the right side. */ 2178 /* Outline on the right side. */
2143 const float outlineOpacity = value_Anim(&d->outlineOpacity); 2179 const float outlineOpacity = value_Anim(&d->outlineOpacity);
2144 if (prefs_App()->hoverOutline && !isEmpty_Array(&d->outline) && outlineOpacity > 0.0f) { 2180 if (prefs_App()->hoverOutline && !isEmpty_Array(&d->outline) && outlineOpacity > 0.0f) {
2145// const int font = uiLabel_FontId; 2181 const int innerWidth = outlineWidth_DocumentWidget_(d);
2146 //iRect outlineRect = initCorners_Rect(topRight_Rect(docBounds), bottomRight_Rect(bounds)); 2182 const int outWidth = innerWidth + 2 * outlinePadding_DocumentWidget_ * gap_UI;
2147 //const int excess = width_Rect(outlineRect) - 75 * gap_UI; 2183 const int topMargin = 0;
2148// if (excess > 0) { 2184 const int bottomMargin = 3 * gap_UI;
2149// adjustEdges_Rect(&outlineRect, 0, 0, 0, excess); 2185 const int scrollMax = scrollMax_DocumentWidget_(d);
2150// } 2186 const int outHeight = outlineHeight_DocumentWidget_(d);
2151// const int margin = gap_UI * d->pageMargin; 2187 const int oversize = outHeight - height_Rect(bounds) + topMargin + bottomMargin;
2152 const int innerWidth = outlineWidth_DocumentWidget_(d);
2153 const int outWidth = innerWidth + 2 * outlinePadding_DocumentWidget_ * gap_UI;
2154 const int topMargin = 0;//d->pageMargin * gap_UI; // + (banner ? banner->visBounds.size.y : 0);
2155 const int bottomMargin = 3 * gap_UI; //d->pageMargin * gap_UI;
2156 iInt2 pos = add_I2(topRight_Rect(bounds), init_I2(-outWidth - width_Widget(d->scroll), topMargin));
2157// const int lineWidth = avail - margin;
2158// pos.y = drawRangeWrap_Text(uiContent_FontId, pos, lineWidth, tmBannerIcon_ColorId,
2159// bannerText_DocumentWidget_(d));
2160// pos.y += gap_UI;
2161 const int scrollMax = scrollMax_DocumentWidget_(d);
2162 const int outHeight = bottom_Rect(((const iOutlineItem *) constBack_Array(&d->outline))->rect);
2163 const int oversize = outHeight - height_Rect(bounds) + topMargin + bottomMargin;
2164 const int scroll = 2188 const int scroll =
2165 (oversize > 0 && scrollMax > 0 ? oversize * d->scrollY / scrollMax_DocumentWidget_(d) 2189 (oversize > 0 && scrollMax > 0 ? oversize * d->scrollY / scrollMax_DocumentWidget_(d)
2166 : 0); 2190 : 0);
2191 iInt2 pos =
2192 add_I2(topRight_Rect(bounds), init_I2(-outWidth - width_Widget(d->scroll), topMargin));
2167 /* Center short outlines vertically. */ 2193 /* Center short outlines vertically. */
2168 if (oversize < 0) { 2194 if (oversize < 0) {
2169 pos.y -= oversize / 2;// + (banner ? banner->visBounds.size.y / 2 : 0); 2195 pos.y -= oversize / 2;
2170 } 2196 }
2171 pos.y -= scroll; 2197 pos.y -= scroll;
2172 setOpacity_Text(outlineOpacity); 2198 setOpacity_Text(outlineOpacity);